PHP实现mysql事务处理_LSGOZJ的博客-CSDN博客

来源: PHP实现mysql事务处理_LSGOZJ的博客-CSDN博客

想要实现事务管理,操作的表引擎类型必须是 InnoDB 类型,在生成表的时候就要声明,因为 mySQL 默认引擎是 MYISAM ;当然,你也可以在生成表之后修改表的引擎:

ALTER TABLE orders ENGINE=INNODB;
1
更多详细可以参照我的另一篇博客:《关于mySQL管理事务处理》,这里用到的表都是那篇博客中创建的表。

下面先写一个小栗子(往orders表和orderdetail表存数据):

<?php
//数据库连接
$link = mySQL_connect(“localhost”,’root’,’root’) or die(“数据库链接失败!”);
//选择数据库
// $db = mysql_select_db(“test_mysql”,$link);
$db = mysql_query(“USE test”);
if(!$db){
echo “数据库连接失败!”;
}
mysql_query(“SET NAMES UTF8”);

//开启事务
$sql1 = “START TRANSACTION”;
mysql_query($sql1);

$ins_sql1 = “INSERT INTO orders(user_id,order_no) VALUES(10,’LSGO123′)”;
$err1 = mysql_query($ins_sql1);

$ins_sql2 = “INSERT INTO orderdetail(order_no,detail) VALUES(‘LSGO123′,’LSGO实验室’)”;
$err2 = mysql_query($ins_sql2);

if(!$err1 || !$err2){
echo “存表出错了”;
mysql_query(“ROLLBACK”);
}else{
echo “存表正确”;
mysql_query(“COMMIT”);
}

mysql_close();
?>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
结果输出“存表正确。”,检查数据库:

mysql> SELECT * FROM orders;
+—-+———+———-+
| id | user_id | order_no |
+—-+———+———-+
| 30 | 10 | LSGO123 |
+—-+———+———-+
1 row in set

mysql> SELECT * FROM orderdetail;
+—-+———-+———-+
| id | order_no | detail |
+—-+———-+———-+
| 12 | LSGO123 | LSGO实验室|
+—-+———-+———-+
1 row in set
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
这证明我们存表确实成功。

现在我们卡一下,使其中的一个表存失败:

$ins_sql1 = “INSERT INTO orders(user_id,order_no) VALUES(10,’LSGO123′)”;
$err1 = mysql_query($ins_sql1);

$ins_sql2 = “INSERT INTO orderdetail(order_no,detail) VALUES(‘LSGO123’,LSGO实验室)”;//这里我故意使出错。
$err2 = mysql_query($ins_sql2);

if(!$err1 || !$err2){
echo “存表出错了”;
mysql_query(“ROLLBACK”);
}else{
echo “存表正确”;
mysql_query(“COMMIT”);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
结果返回“存表失败了”,检查两张表,发现都没存进去,证明事务起作用了。
通过以上的例子,我们可以看到,事务处理可以用来维护数据库的完整性,它保证成批的MySQL操作要么完全执行,要么完全不执行,也就是说当要求某几个表同时存或同时不存的时候,就该用事务了。

现在该说一下事务里面的保留点了

引用前面说的那篇博客里面一个例子:
现在假想这么一个问题,当一个新用户购买我的东西的时候,我要分别存customer表、orders表、orderdetail表,假如某个故障阻止了这个存储过程,那么数据库会发生什么?
1、customer表存失败了,那么我们就不能让它继续往orders和orderdetail表存。
2、customer成功了,但orders表失败了,那么customer是可以允许成功的,毕竟某个用户没有订单是完全合法的,但是orders失败了,orderdetail就不能往下存了,因为orders和orderdetail是同步的。

怎么实现?这里用保留点实现部分回退事务。

//开启事务
$sql1 = “START TRANSACTION”;
mysql_query($sql1);

$ins_sql3 = “INSERT INTO customer(name,age) VALUES(‘奔跑吧LSGO’,20)”;
$err3 = mysql_query($ins_sql3);

//设置保留点
mysql_query(“SAVEPOINT ins_1_2”);

$ins_sql1 = “INSERT INTO orders(user_id,order_no) VALUES(10,’LSGO123′)”;
$err1 = mysql_query($ins_sql1);

$ins_sql2 = “INSERT INTO orderdetail(order_no,detail) VALUES(‘LSGO123′,’LSGO实验室’)”;
$err2 = mysql_query($ins_sql2);

if(!$err1 || !$err2){
//回滚至保留点处,即不存orders表和orderdetail表
echo “orders和orderdetail存失败了!”;
mysql_query(“ROLLBACK TO SAVEPOINT ins_1_2”);
}
if($err3){
echo “存表成功!”;
mysql_query(“COMMIT”);
}else{
echo “customer存失败了!”;
mysql_query(“ROLLBACK”);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
结果返回“存表成功”,就是整个事务都成功,三个表自然也存了;

再来?

//开启事务
$sql1 = “START TRANSACTION”;
mysql_query($sql1);

$ins_sql3 = “INSERT INTO customer(name,age) VALUES(奔跑吧LSGO,20)”;//注意,这里我故意让他出错
$err3 = mysql_query($ins_sql3);

//设置保留点
mysql_query(“SAVEPOINT ins_1_2”);

$ins_sql1 = “INSERT INTO orders(user_id,order_no) VALUES(10,’LSGO123′)”;
$err1 = mysql_query($ins_sql1);

$ins_sql2 = “INSERT INTO orderdetail(order_no,detail) VALUES(‘LSGO123′,’LSGO实验室’)”;
$err2 = mysql_query($ins_sql2);

if(!$err1 || !$err2){
//回滚至保留点处,即不存orders表和orderdetail表
echo “orders或orderdetail存失败了!”;
mysql_query(“ROLLBACK TO SAVEPOINT ins_1_2”);
}
if($err3){
echo “存表成功!”;
mysql_query(“COMMIT”);
}else{
echo “customer存失败了!”;
mysql_query(“ROLLBACK”);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
结果返回“customer存失败了!”,按照问题的要求,customer表失败,其它两个表也失败了,事实上也是这样的,orders表和orderdetail表没有存。

当我使保留点后的代码出错,结果返回“orders或orderdetail存失败了!”,然后看数据库,发现customer表存成功了,其它两表存失败了。这也满足了问题的要求。

在网上看到一篇博客说在表引擎不是INNODB的情况下,我们也可以实现简单的事务处理,这里就叫它 “仿事务”吧,原理就是把mysql自动提交更改关掉,手动提交代码,就类似于手动COMMIT。
直接上代码:

mysql_query(“SET AUTOCOMMIT=0”); //设置mysql不自动提交,需自行用commit语句提交
$sql1 = “INSERT INTO customer(name,age) VALUES(‘LSGO实验室’,20)”;
$sql2 = “INSERT INTO orders(user_id,order_no) VALUES(12,’LSGO123′)”;
$res1 = mysql_query($sql1);
$res2 = mysql_query($sql2);
if($res1 && $res2){
mysql_query(“COMMIT”);
echo ‘提交成功。’;
}else{
mysql_query(“ROLLBACK”);
echo ‘数据回滚。’;
}
mysql_query(“SET AUTOCOMMIT=1”);
//事务处理完时别忘记mysql_query(“SET AUTOCOMMIT=1”);恢复自动提交,不然会影响到后面的操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
这个方法固然是走得通的,但是没法实现部分回退的功能,因此还是推荐用前面介绍的方法。

事务处理在thinkphp 中相当简单,毕竟thinkphp中已经封装好相关方法,你只需要调用即可。

//实例化的数据库对象
$model = new Model();
//开启事务
$model->startTrans();
//这里你也可以用具体的一张表的实例即可,如
//$orders = M(‘Orders’);
//$orders->startTrans();

//数据操作
$orders = M(‘Orders’);
$customer = M(‘Customer’);
$res1 = $orders->where(“user_id = 10”)->delete();
$res2 = $customer->where(“age = 20”)->delete();

if($res1 && $res2){
echo “成功啦!”;
$model->commit();
}else{
echo “滚~~~”;
$model->rollback();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
至此,我掌握的事务处理已经讲完了。
————————————————
版权声明:本文为CSDN博主「LSGOZJ」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/baidu_30000217/article/details/50375074

赞(0) 打赏
分享到: 更多 (0)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏