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 }
