文档介绍:PHP中实现MySQL嵌套事务的两种解决方案一、问题起源在MySQL的官方文档中有明确的说明不支持嵌套事务: 代码如下: . 但是在我们开发一个复杂的系统时难免会无意中在事务中嵌套了事务,比如A函数调用了B函数,A函数使用了事务,并且是在事务中调用了B函数,B函数也有一个事务,这样就出现了事务嵌套。这时候其实A的事务就意义不大了,为什么呢?上面的文档中就有提到,简单的翻译过来就是: 代码如下: 当执行一个STARTTRANSACTION指令时,mit操作。所以我们就要在系统架构层面来支持事务的嵌套。所幸的是在一些成熟的ORM框架中都做了对嵌套的支持,比如doctrine或者laravel。接下来我们就一起来看下这两个框架是怎样来实现的。友情提示,这两个框架的函数和变量的命名都比较的直观,虽然看起来很长,但是都是通过命名就能直接得知这个函数或者变量的意思,所以不要一看到那么一大坨就被吓到了:) 二、doctrine的解决方案首先来看下在doctrine中创建事务的代码(干掉了不相关的代码): 代码如下: publicfunctionbeginTransaction() { ++$this->_transactionNestingLevel; if($this->_transactionNestingLevel==1){ $this->_conn->beginTransaction(); }elseif($this->_nestTransactionsWithSavepoints){ $this->createSavepoint($this->_getNestedTransactionSavePointName()); } } 这个函数的第一行用一个_transactionNestingLevel来标识当前嵌套的级别,如果是1,也就是还没有嵌套,那就用默认的方法执行一下STARTTRANSACTION就ok了,如果大于1,也就是有嵌套的时候,她会帮我们创建一个savepoint,这个savepoint可以理解为一个事务记录点,当需要回滚时可以只回滚到这个点。然后看下rollBack函数: 代码如下: publicfunctionrollBack() { if($this->_transactionNestingLevel==0){ throwConnectionException::noActiveTransaction(); } if($this->_transactionNestingLevel==1){ $this->_transactionNestingLevel=0; $this->_conn->rollback(); $this->_isRollbackOnly=false; }elseif($this->_nestTransactionsWithSavepoints){ $this->rollbackSavepoint($this->_getNestedTransactionSavePointName())