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 }
|