微信扫一扫打赏支持

thinkphp事务处理以及无效时的解决方案(整理)

thinkphp事务处理以及无效时的解决方案(整理)

一、总结

一句话总结:要程序里面支持事务,首先连接的数据库和数据表必须支持事务 mysql

 

1、InnoDB和MyISAM对事务的支持怎么样

InnoDB支持事务

MyISAM不支持事务

 

2、thinkphp中事务无效如何解决?

可以首先尝试将数据表存储引擎改为:InnoDB

 

3、在哪里修改数据表的存储引擎?

design table->Options

 

 

二、thinkphp 的事务回滚处理 和 原始PHP的事务回滚实例

1、要程序里面支持事务,首先连接的数据库和数据表必须支持事务 mysql   为例:

数据库InnoDB支持 transactions

 

数据表支持事务:InnoDB  支持transaction

2、框架thinkphp  支持事务代码

public function testrollback(){
$model1 = D('item');
$model2 = D('vote');
$model1->startTrans();
$res1 = $model1->where('id = 5')->delete();
$res2 = $model2->where('id = 2')->delete();
dump($res1);
dump($res2);
if($res1 && $res2){
$model1->commit();   //只有$res1 和  $res2  都执行成功是才真正执行上面的数据库操作
dump("commit");
}else{
$model1->rollback();  //  条件不满足,回滚
dump("rollback");
}
dump("over");
exit;
}

 

 

 

3、原始PHP 代码事务实例

方法一:只支持数据库和数据表都是 innoDB  的情况

public function  rollbackoriginal1(){
        $conn = mysql_connect('127.0.0.1','summerzi','summerzi') or die('DB connection failed!');
        mysql_select_db('summer',$conn);
        mysql_query('set names "GBK"');
        mysql_query('BEGIN');
        $sql1 = "INSERT INTO `summer_userdata`(`uid`,`type`,`target_id`) VALUES(41,1,233);";
        $sql2 = "INSERT INTO `summer_userdata`(`uid`,`type`,`target_id`) VALUES(fdfd,2,235);";
        $res1 = mysql_query($sql1);
        $res2  = mysql_query($sql2);
        dump($sql1);
        dump($sql2);
        dump($res1);
        dump($res2);
        if($res1 && $res2){
            mysql_query('COMMIT');
            dump('commit success!');
        }else{
            mysql_query('ROLLBACK');
            dump('commit failed, rollback!');
        }
        mysql_query('END');

    }

方法二:(注意:对于不支持事务的MyISAM引擎数据库可以使用表锁定的方法

public function rollbackoriginal2(){
        $conn = mysql_connect('127.0.0.1','summerzi','summerzi') or die('DB connection failed!');
        mysql_select_db('summer',$conn);
        mysql_query('set names "GBK"');
        mysql_query('SET AUTOCOMMIT=0');////设置mysql不自动提交,需自行用commit语句提交
        $sql1 = "INSERT INTO `summer_userdata`(`uid`,`type`,`target_id`) VALUES(41,1,233);";
        $sql2 = "INSERT INTO `summer_userdata`(`uid`,`type`,`target_id`) VALUES(44,2,235);";
        //mysql_query("LOCK TABLES `hmbl_userdata` WRITE");//锁定表
        $res1 = mysql_query($sql1);
        $res2  = mysql_query($sql2);
        dump($sql1);
        dump($sql2);
        dump($res1);
        dump($res2);
        //mysql_query("UNLOCK TABLES");//解除锁定
        if($res1 && $res2){
            mysql_query('COMMIT');
            dump('commit success!');
        }else{
            mysql_query('ROLLBACK');
            dump('commit failed, rollback!');
        }
        mysql_query("SET AUTOCOMMIT=1");
        mysql_query('END');
        

    }

php + mysql  对事务的处理比较简单,涉及到业务中多个数据操作,就可以考虑用事务处理

 

参考:thinkphp 的事务回滚处理 和 原始PHP的事务回滚实例 - summerzi - 博客园
https://www.cnblogs.com/summerzi/archive/2015/04/05/4393790.html

 

三、thinkphp事务处理无效时的解决办法,一击命中!

处理事务的时候,发现没有办法rollback,找了好久,我终于发现了问题所在:

以下干货:

数据表存储引擎改为:InnoDB

 

参考:thinkphp事务处理无效时的解决办法,一击命中! - CSDN博客
https://blog.csdn.net/yhq1988923/article/details/53516830

 

四、ThinkPHP 事务处理 (事务回滚) 、异常处理代码

事务代码写在try-catch之中

 1     $trans_result = true;
 2     $trans = M();
 3     $trans->startTrans();   // 开启事务
 4 
 5     try {   // 异常处理
 6         // 更新实施
 7         $busbidList = M("busbid")->where($map)->select();
 8         foreach($busbidList as $k => $v) {
 9             $map['id'] = $busbidList[$k]['id'];
10             $result = M('busbid')->where($map)->data($data)->save();
11             if ($result === false) {
12                 throw new Exception(“错误原因”);
13             }
14         }
15     } catch (Exception $ex) {
16         $trans_result = false;
17         // 记录日志
18         Log::record("== xxx更新失败 ==", 'DEBUG');
19         Log::record($ex->getMessage(), 'DEBUG');
20     }
21 
22     if ($trans_result === false) {
23         $trans->rollback();
24         // 更新失败
25         $array['status'] = 0;
26     } else {
27         $trans->commit();
28         // 更新成功
29         $array['status'] = 1;
30     }

 

 

五、数据表修改储存引擎位置

design table->Options

 

 

六、thinkphp事务中if($ans1&&$ans2){}else{}方式和try{}catch{}方式事务操作的区别在哪里?

if_else方式是两个都要影响了数据库才能执行

try_catch方式是只要不发生异常就执行。

比如数据表中有id为12345的字段

比如说我们现在删除id为5和6的字段

在if_else中就是rollback,

在try_catch中就是commit

 

 1 //19、测试事务操作
 2 public function test18(){
 3     Db::startTrans();
 4     $ans1=db('myself_goods')->delete(6);
 5     $ans2=db('myself_goods')->delete(5);
 6     if($ans1&&$ans2){
 7         // 提交事务
 8         dump('commit');
 9         Db::commit();
10     }else{
11         // 回滚事务
12         Db::rollback();
13         dump('rollback');
14     }
15 }
16 
17 //18、测试事务操作
18 public function test17(){
19     // 启动事务
20     Db::startTrans();
21     try{
22         $ans1=db('myself_goods')->delete(6);
23         $ans2=db('myself_goods')->delete(7);
24         dump('$ans1:  '.$ans1);
25         dump('$ans2:  '.$ans2);
26         // 提交事务
27         dump('commit');
28         Db::commit();
29     } catch (\Exception $e) {
30         // 回滚事务
31         Db::rollback();
32         dump('rollback');
33     }
34 }

 

 

 
 
 
 

 

 

 
posted @ 2018-08-24 09:43  范仁义  阅读(3939)  评论(0编辑  收藏  举报