在PHP中实现MySQL嵌套事务的两种解决方案

第一,问题的根源

MySQL的正式文档中有一个不支持嵌套事务的明确说明:

复制代码代码如下所示:

事务不能嵌套。这是隐式的结果,也被称为以下三个方面。



但在我们的一个复杂系统的发展必然会在不经意间交易中的嵌套事务,比如一个函数调用B函数,函数在交易中使用事务,称为B,B的函数是一个交易,所以这是一个嵌套事务。事实上,在这点,一个事务不显著。为什么正如上面提到的,简单的翻译是:

复制代码代码如下所示:

执行启动事务指令时,将隐式执行提交操作。



所以我们要支持在系统架构层面事务的嵌套,嵌套的支持已经在一些成熟的ORM框架,如学说或laravel。然后我们会看看这两种框架的实现。

友好的提示,这两个框架的函数和变量的命名更直观。虽然它们看起来很长,但它们可以通过命名直接了解这个函数或变量的含义,所以不要害怕看到一个大肿块。

二、学说解

首先,看看在理论中创建事务的代码(干掉无关代码):

复制代码代码如下所示:

公共函数开始()

{

+ +美元-> _transactionnestinglevel;

如果(美元-> _transactionnestinglevel = = 1){

这_conn美元-> ->开始();

如果(美元-> _nesttransactionswithsavepoints){ }

这createsavepoint(美元->美元-> _getnestedtransactionsavepointname());

}

}



这个函数是一个_transactionnestinglevel识别当前嵌套层次的第一行,如果是1,而不是嵌套的,则使用默认的方法在确定执行开始交易,如果超过1,那是嵌套的,她将帮助我们创建一个保存点,保存点可以理解一个交易记录,当你需要回滚只能滚回点。

然后看看回滚函数:

复制代码代码如下所示:

公共函数回滚()

{

如果(美元-> _transactionnestinglevel = = 0){

把connectionexception::noactivetransaction();

}

如果(美元-> _transactionnestinglevel = = 1){

美元-> _transactionnestinglevel = 0;

这_conn美元-> ->回滚();

美元-> _isrollbackonly = false;

如果(美元-> _nesttransactionswithsavepoints){ }

这rollbacksavepoint(美元->美元-> _getnestedtransactionsavepointname());

——美元-> _transactionnestinglevel;

{人}

美元-> _isrollbackonly =真;

——美元-> _transactionnestinglevel;

}

}



你可以看到,处理的方式也很简单,如果是1级,直接回复,否则回滚到以前的保存点。

然后我们继续研究提交函数:

复制代码代码如下所示:

公共函数提交()

{

If ($this->_transactionNestingLevel = = 0) {

把connectionexception::noactivetransaction();

}

如果(美元-> _isrollbackonly){

把connectionexception::commitfailedrollbackonly();

}

如果(美元-> _transactionnestinglevel = = 1){

这_conn美元-> ->提交();

如果(美元-> _nesttransactionswithsavepoints){ }

这releasesavepoint(美元->美元-> _getnestedtransactionsavepointname());

}

——美元-> _transactionnestinglevel;

}



来吧,别费心解释这件事:

三、laravel溶液

laravel的处理方式是比较简单和粗糙。让我们先看看创建事务的操作:

复制代码代码如下所示:

公共函数开始()

{

+ $此事务;

如果($ =事务= 1)

{

美元-> PDO ->开始();

}

}



你感觉怎么样这么简单,对吧先判断几笔交易,如果是第一次,OK,交易开始,否则没什么事,那为什么不做呢继续关注回滚操作:

复制代码代码如下所示:

公共函数回滚()

{

如果($ =事务= 1)

{

$ > >事务= 0;

美元-> ->回滚(PDO);

}

其他的

{

——$ >事务;

}

}



你明白了吗真正的回滚当前事务时,只有一个,否则只有降低到一个操作。这就是为什么laravel说处理相对比较简单粗暴,这实际上是在嵌套的内部木有真正的事务,只有一个整体交易的外层,虽然简陋,但也解决了一个新的交易在内部造成犯罪问题。这是原则,保持完整的提交代码复制过来!

复制代码代码如下所示:

公共函数提交()

{

如果(美元->交易= = 1)(美元-> PDO ->提交);

——$ >事务;

}