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 }

 

 

 
 
 
 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM