1. MySQL默认自动提交(autocommit=1),如果要开启事务,先关闭自动提交(autocommit=0);
  2. InnoDB支持事务,MyISAM不支持;
  3. MySQL不支持事务嵌套;已经开启事务后,再开启事务(start transaction),会隐式的提交(commit)上一个事务。

MySQL中可以通过部分事务(savepoint)来实现嵌套

  1. TRUNCATE nested_transaction;
  2. BEGIN;
  3. INSERT INTO `nested_transaction`(id) VALUES(1);
  4. SAVEPOINT t1;
  5. INSERT INTO `nested_transaction`(id) VALUES(2);
  6. ROLLBACK TO SAVEPOINT t1;
  7. COMMIT;

id
--------
1

PHP中Laravel中事务嵌套(ManagesTransactions.php)

  1. <?php
  2.  
  3. namespace Illuminate\Database\Concerns;
  4.  
  5. use Closure;
  6. use Exception;
  7. use Throwable;
  8.  
  9. trait ManagesTransactions
  10. {
  11. /**
  12. * Execute a Closure within a transaction.
  13. *
  14. * @param \Closure $callback
  15. * @param int $attempts
  16. * @return mixed
  17. *
  18. * @throws \Exception|\Throwable
  19. */
  20. public function transaction(Closure $callback, $attempts = 1)
  21. {
  22. for ($currentAttempt = 1; $currentAttempt <= $attempts; $currentAttempt++) {
  23. $this->beginTransaction();
  24.  
  25. // We'll simply execute the given callback within a try / catch block and if we
  26. // catch any exception we can rollback this transaction so that none of this
  27. // gets actually persisted to a database or stored in a permanent fashion.
  28. try {
  29. return tap($callback($this), function ($result) {
  30. $this->commit();
  31. });
  32. }
  33.  
  34. // If we catch an exception we'll rollback this transaction and try again if we
  35. // are not out of attempts. If we are out of attempts we will just throw the
  36. // exception back out and let the developer handle an uncaught exceptions.
  37. catch (Exception $e) {
  38. $this->handleTransactionException(
  39. $e, $currentAttempt, $attempts
  40. );
  41. } catch (Throwable $e) {
  42. $this->rollBack();
  43.  
  44. throw $e;
  45. }
  46. }
  47. }
  48.  
  49. /**
  50. * Handle an exception encountered when running a transacted statement.
  51. *
  52. * @param \Exception $e
  53. * @param int $currentAttempt
  54. * @param int $maxAttempts
  55. * @return void
  56. *
  57. * @throws \Exception
  58. */
  59. protected function handleTransactionException($e, $currentAttempt, $maxAttempts)
  60. {
  61. // On a deadlock, MySQL rolls back the entire transaction so we can't just
  62. // retry the query. We have to throw this exception all the way out and
  63. // let the developer handle it in another way. We will decrement too.
  64. if ($this->causedByDeadlock($e) &&
  65. $this->transactions > 1) {
  66. --$this->transactions;
  67.  
  68. throw $e;
  69. }
  70.  
  71. // If there was an exception we will rollback this transaction and then we
  72. // can check if we have exceeded the maximum attempt count for this and
  73. // if we haven't we will return and try this query again in our loop.
  74. $this->rollBack();
  75.  
  76. if ($this->causedByDeadlock($e) &&
  77. $currentAttempt < $maxAttempts) {
  78. return;
  79. }
  80.  
  81. throw $e;
  82. }
  83.  
  84. /**
  85. * Start a new database transaction.
  86. *
  87. * @return void
  88. * @throws \Exception
  89. */
  90. public function beginTransaction()
  91. {
  92. $this->createTransaction();
  93.  
  94. ++$this->transactions;
  95.  
  96. $this->fireConnectionEvent('beganTransaction');
  97. }
  98.  
  99. /**
  100. * Create a transaction within the database.
  101. *
  102. * @return void
  103. */
  104. protected function createTransaction()
  105. {
  106. if ($this->transactions == 0) {
  107. try {
  108. $this->getPdo()->beginTransaction();
  109. } catch (Exception $e) {
  110. $this->handleBeginTransactionException($e);
  111. }
  112. } elseif ($this->transactions >= 1 && $this->queryGrammar->supportsSavepoints()) {
  113. $this->createSavepoint();
  114. }
  115. }
  116.  
  117. /**
  118. * Create a save point within the database.
  119. *
  120. * @return void
  121. */
  122. protected function createSavepoint()
  123. {
  124. $this->getPdo()->exec(
  125. $this->queryGrammar->compileSavepoint('trans'.($this->transactions + 1))
  126. );
  127. }
  128.  
  129. /**
  130. * Handle an exception from a transaction beginning.
  131. *
  132. * @param \Exception $e
  133. * @return void
  134. *
  135. * @throws \Exception
  136. */
  137. protected function handleBeginTransactionException($e)
  138. {
  139. if ($this->causedByLostConnection($e)) {
  140. $this->reconnect();
  141.  
  142. $this->pdo->beginTransaction();
  143. } else {
  144. throw $e;
  145. }
  146. }
  147.  
  148. /**
  149. * Commit the active database transaction.
  150. *
  151. * @return void
  152. */
  153. public function commit()
  154. {
  155. if ($this->transactions == 1) {
  156. $this->getPdo()->commit();
  157. }
  158.  
  159. $this->transactions = max(0, $this->transactions - 1);
  160.  
  161. $this->fireConnectionEvent('committed');
  162. }
  163.  
  164. /**
  165. * Rollback the active database transaction.
  166. *
  167. * @param int|null $toLevel
  168. * @return void
  169. */
  170. public function rollBack($toLevel = null)
  171. {
  172. // We allow developers to rollback to a certain transaction level. We will verify
  173. // that this given transaction level is valid before attempting to rollback to
  174. // that level. If it's not we will just return out and not attempt anything.
  175. $toLevel = is_null($toLevel)
  176. ? $this->transactions - 1
  177. : $toLevel;
  178.  
  179. if ($toLevel < 0 || $toLevel >= $this->transactions) {
  180. return;
  181. }
  182.  
  183. // Next, we will actually perform this rollback within this database and fire the
  184. // rollback event. We will also set the current transaction level to the given
  185. // level that was passed into this method so it will be right from here out.
  186. $this->performRollBack($toLevel);
  187.  
  188. $this->transactions = $toLevel;
  189.  
  190. $this->fireConnectionEvent('rollingBack');
  191. }
  192.  
  193. /**
  194. * Perform a rollback within the database.
  195. *
  196. * @param int $toLevel
  197. * @return void
  198. */
  199. protected function performRollBack($toLevel)
  200. {
  201. if ($toLevel == 0) {
  202. $this->getPdo()->rollBack();
  203. } elseif ($this->queryGrammar->supportsSavepoints()) {
  204. $this->getPdo()->exec(
  205. $this->queryGrammar->compileSavepointRollBack('trans'.($toLevel + 1))
  206. );
  207. }
  208. }
  209.  
  210. /**
  211. * Get the number of active transactions.
  212. *
  213. * @return int
  214. */
  215. public function transactionLevel()
  216. {
  217. return $this->transactions;
  218. }
  219. }

也可以只开启一个事物,判断如果是嵌套事务,则不做操作直接返回。

MySQL 事务嵌套的更多相关文章

  1. MySql中的事务嵌套

    1.Mysql中的事务必须是InnoDB.Berkeley DB引擎,myisam不支持. 2.Mysql是不支持嵌套事务的,开启了一个事务的情况下,再开启一个事务,会隐式的提交上一个事务. 3.My ...

  2. Mysql事务及行级锁的理解

    在最近的开发中,碰到一个需求签到,每个用户每天只能签到一次,那么怎么去判断某个用户当天是否签到呢?因为当属表设计的时候,每个用户签到一次,即向表中插入一条记录,根据记录的数量和时间来判断用户当天是否签 ...

  3. 第五章 MySQL事务,视图,索引,备份和恢复

    第五章 MySQL事务,视图,索引,备份和恢复 一.事务 1.什么是事务 事务是一种机制,一个操作序列,它包含了一组数据库操作命令,并且把所有的命令作为一个整体一起向系统提交或撤销操作请求.要么都执行 ...

  4. Mysql事务及行级锁

    事务隔离级别 数据库事务隔离级别,只是针对一个事务能不能读取其它事务的中间结果. Read Uncommitted (读取未提交内容) 在该隔离级别,所有事务都可以看到其他未提交事务的执行结果.本隔离 ...

  5. 10.mysql事务管理及python操作

    在用户操作MySQL过程中,对于一般简单的业务逻辑或中小型程序而言,无需考虑应用MySQL事务.但在比较复杂的情况下,往往用户在执行某些数据操作过程中,需要通过一组SQL语句执行多项并行业务逻辑或程序 ...

  6. mysql事务的开启

    mysql事务的开启 对于一个MYSQL数据库(InnoDB),事务的开启与提交模式无非下面这两种情况: 1>若参数autocommit=0,事务则在用户本次对数据进行操作时自动开启,在用户执行 ...

  7. Mysql事务探索及其在Django中的实践(二)

    继上一篇<Mysql事务探索及其在Django中的实践(一)>交代完问题的背景和Mysql事务基础后,这一篇主要想介绍一下事务在Django中的使用以及实际应用给我们带来的效率提升. 首先 ...

  8. MySQL实现嵌套集合模型

    MySQL实现嵌套集合模型 译文主要是介绍如何用MySQL来存储嵌套集合数据.在其中会增加一些自己的理解,也会删除掉一些自认为无用的废话. 这篇文章主要讲的是嵌套集合模型,所以邻接表不是本文的重点,简 ...

  9. MySQL 事务

    MySQL 事务主要用于处理操作量大,复杂度高的数据.比如说,在人员管理系统中,你删除一个人员,你即需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这样,这些数据库操作语句就构成 ...

随机推荐

  1. Matlab Tricks(十五) —— 圆的正确画法

    使用参数方程, phi = 0:0.01:2*pi; x = cos(phi); y = sin(phi); axis equal plot(x, y) 根据参数方程,显然,圆心在 (0, 0),半径 ...

  2. mysql安装出现应用程序无法正常启动(oxc000007b)的解决方案

    原文:mysql安装出现应用程序无法正常启动(oxc000007b)的解决方案 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/IUNIQUE/art ...

  3. 在嵌入式程序中QT去掉鼠标指针

    在像arm的QT编程当中,一般都是使用触摸来操作,当是我们运行程序的时候会发现总是有个鼠标箭头在那里,下面介绍种方法将其给去掉.这样就漂亮多了.在main()函数加入 #include <QWS ...

  4. 经典书单、站点 —— 大数据/数据分析/R语言

    1. 科普.入门 <大数据智能>,刘知远.崔安顺等著: 特色:系统,宏观和全面: 2. R 语言站点 http://langdawei.com/:R 语言数据采集与可视化:

  5. iOS8的APP过渡过程

    1. 2. watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveWluX3hpYW53ZWk=/font/5a6L5L2T/fontsize/400/fill/ ...

  6. MySQL SYS CPU高的案例分析(二)

    原文:MySQL SYS CPU高的案例分析(二) 后面又做了补充测试,增加了每秒context switch的监控,以及SQL执行时各步骤消耗时间的监控. [测试现象一] 启用1000个并发线程的压 ...

  7. Oracle使用dblink连接SqlServer

    使用场景:当你需要从ORACLE数据库上访问另一台SqlServer数据库的数据时,Oracle提供了一个工具:gateways.通过这个工具,你可以创建dblink来连接sqlserver或其他不同 ...

  8. (015)实现一个函数来检查是否平衡树(keep it up)

    实现一个函数来检查是否平衡树.这个问题而言. 平衡指的是这棵树随意两个叶子结点到根结点的距离之差不大于1. 这个题我们能够採用暴力搜索,找到叶子节点到根节点的最小值和最大值.然后他们的差假设大于1就不 ...

  9. 使用lead分析功能相似的结构9*9乘法口诀功能

    今天兄弟们的帮助,数据库,具有数据如下面的表: no  name 1    a 2    b 3    c 4    d 怎样用一个sql显演示样例如以下结果: ab ac ad bc bd cd 对 ...

  10. spring boot 使用 pageHelper插件

    按照github上的教程集成到spring boot pom文件引用需要改一下,教程的pom文件引用: 工程中要用以下方式 <!--分页--> <dependency> < ...