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之中

     $trans_result = true;
$trans = M();
$trans->startTrans(); // 开启事务 try { // 异常处理
// 更新实施
$busbidList = M("busbid")->where($map)->select();
foreach($busbidList as $k => $v) {
$map['id'] = $busbidList[$k]['id'];
$result = M('busbid')->where($map)->data($data)->save();
if ($result === false) {
throw new Exception(“错误原因”);
}
}
} catch (Exception $ex) {
$trans_result = false;
// 记录日志
Log::record("== xxx更新失败 ==", 'DEBUG');
Log::record($ex->getMessage(), 'DEBUG');
} if ($trans_result === false) {
$trans->rollback();
// 更新失败
$array['status'] = 0;
} else {
$trans->commit();
// 更新成功
$array['status'] = 1;
}

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

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 }
 
 
 
 
 

thinkphp事务处理以及无效时的解决方案(整理)的更多相关文章

  1. Android RecyclerView遇到notifyDataSetChanged无效时的解决方案

    一.简述 不管AbsListView(ListView.GridView)或是新出的RecyclerView,在使用notifyDataSetChanged方法更新列表数据时,一定要保证数据为同个对象 ...

  2. 当target属性在XHTML script中无效时

    <a href="#" target=_blank></a>target此属性能够使链接在新窗口打开,但是在XHTML script中无效时. 那么解决方案 ...

  3. Qt之高DPI显示器(一) - 解决方案整理

    目录 DPI发展 1.PPI 2.DPI 一.Win自适应系统 二.Qt机制 1.Windows系统DWM缩放 2. Qt适配高DPI 3.适配DPI结论 三.Qt适配 四.自己适配 1.窗口大小 2 ...

  4. DataGridView 行数据验证:当输入数据无效时不出现红色感叹号的Bug

    private void dgvView_CellValidating(object sender, DataGridViewCellValidatingEventArgs e){       if ...

  5. python解释器的安装;python2与python3同时在环境变量中时的解决方案

    新文档 html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,addres ...

  6. C#调试含有源代码的动态链接库遇见there is no source code available for the current location提示时的解决方案

    C#调试含有源代码的动态链接库遇见there is no source code available for the current location提示时的解决方案: 1.首先试最常规的方法:Cle ...

  7. IDE按住ctrl 打开单元 无效时 的方法

    一般打开单元无效时 是由于程序有错误,若程序没有错误 可以重新build一下 再试. 若实在不行 就右键---open at cursor

  8. Android 开发时使用 ViewPager 的问题及解决方案整理

    1. ViewPager 的页面重置问题 当我们使用ViewPager控件时,假设我们的ViewPager有三页,当我们第一次启动ViewPager显示第一页的时候,ViewPager会预加载第二页, ...

  9. Base-64 字符数组或字符串的长度无效等问题解决方案

    项目特殊需要,调用ActiveX三维控件进行控件某一特殊部位的截图操作,这个截图保存由ActiveX控件控制保存到本地是没问题的,现在需要将这个截图上传到服务器,多人共享,就牵扯到需要读取本地文件…… ...

随机推荐

  1. Android 查看CPU及内存

    借助getprop.dumpsys来了解一些系统相关信息. 一.getprop adb shell cat /system/build.prop 文件中存放的是用于启动系统时需要的配置文件,通常可以通 ...

  2. 【习题 8-19 UVA-1312】Cricket Field

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 添加两个y坐标0和h 然后从这n+2个y坐标中任选两个坐标,作为矩形的上下界. 然后看看哪些点在这个上下界中. 定义为坐标集合S S ...

  3. 【Henu ACM Round#19 F】Dispute

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 这一题和这一题很像 (链接 ) 会发现如果a[i]!=b[i]那么就按下i就好了. 然后改变和他相邻的点. 此后a[i]再也不可能和 ...

  4. ArcGIS api for javascript——加入地图并显示当前地图范围

    描述 这个示例使用Map.extent property属性接收地图范围的左下角和右上角坐标 "书签". 使用下列行创建地图: var map = new esri.Map(&qu ...

  5. ImageLoader的简单分析(二)

    在<ImageLoader的简单分析>这篇博客中对IImageLoader三大组件的创建过程以及三者之间的关系做了说明.同一时候文章的最后也简单的说明了一下ImageLoader是怎么通过 ...

  6. 同一个事务里 查询 已删除可是未提交的数据[bug记录]

    前几天犯了个低级错误.在一个事务方法里老是查询不到某条记录,可是debug卡住时,用db工具查.又能查出值. 经过一番折腾,原来是我在同一个事务里 查询 了已删除可是未提交的数据.当然查询不到了! . ...

  7. C++学习笔记31,指向引用的指针(3)

    我们来看一个简单的指向引用的指针的样例. #include <iostream> using namespace std; int main(){ int x=10; int y=20; ...

  8. oc数据类型分类

    OC数据类型能够分为 基本类型.构造类型.指针类型.空类型 基本类型可分为 整型.字符型.枚举型.浮点型(float类型.double类型) 构造类型可分为 数组类型.结构体类型.公用体类型 指针类型 ...

  9. RPC和Socket

    RPC和Socket的区别 rpc是通过什么实现啊?socket! RPC(Remote Procedure Call,远程过程调用)是建立在Socket之上的,出于一种类比的愿望,在一台机器上运行的 ...

  10. SQL一列的合并连起来

    CREATE TABLE #temp( ID INT, name NVARCHAR(max), age int, address ) ) insert into #temp select ID, na ...