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 }