more-icon
MySQL 事务嵌套解决方案小结

  MySQL 事务机制被广泛用于处理操作量大、复杂度高的数据,日常业务中也很常见。在默认的 MySQL 配置下,事务默认是自动提交的,因此要显式地开启一个事务务须使用命令 BEGIN 或 START TRANSACTION,或者执行命令 SET AUTOCOMMIT=0,用来禁止使用当前会话的自动提交。


  MySQL 官方文档中,明确的说明了不支持嵌套事务嵌套。但是在我们开发一个复杂的系统时,由于思维的局限性,函数之间相互调用中,事务的嵌套很难彻底避免。

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
32
33
34
35
mysql> SELECT `value` FROM tmptable.transaction_test;
+-------+
| value |
+-------+
| 1 |
+-------+
1 row in set (0.00 sec)

mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO tmptable.transaction_test (`value`) VALUES ( '2' );
Query OK, 1 row affected (0.01 sec)

mysql> START TRANSACTION;
Query OK, 0 rows affected (0.03 sec)

mysql> INSERT INTO tmptable.transaction_test (`value`) VALUES ( '3' );
Query OK, 1 row affected (0.02 sec)

mysql> COMMIT;
Query OK, 0 rows affected (0.04 sec)

mysql> ROLLBACK;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT `value` FROM tmptable.transaction_test;
+-------+
| value |
+-------+
| 1 |
| 2 |
| 3 |
+-------+
3 rows in set (0.00 sec)

  这段 SQL 的执行结果,按常规思维理解应该是 commit 操作提交了 2 的insert,rollback 操作回滚了 3 的 insert,最终结果应该是 1, 2。然而事实上,看上去 MySQL 只是执行了其中的 commit 操作,后续的 rollback 并没有带来数据上的改变。当 SQL 解释器遇到 START TRANSACTION 时候会触发 commit,也就是说 2 的 insert 操作在第二次开启事务时,已经被隐式地提交了。

ORM 中常见的解决思路

关注
分类