当前位置: 首页 > 科技观察

《MySQL数据库》事务嵌套解决方案

时间:2023-03-20 18:14:54 科技观察

前言当我们开发一个复杂的系统时,可能经常会出现这样的场景:比如函数A调用函数B,而函数A和函数B都使用了Transactions,于是出现了事务嵌套。MySQL官方文档中明确表示MySQL不支持嵌套事务:Transactionscannotbenested。这是在您发出STARTTRANSACTION语句或其同义词之一时对任何当前事务执行隐式提交的结果。那么我们如何解决MySQL事务嵌套问题呢?解决方案目前PHP圈内常见的解决方案有两种,一种是以Doctrine为代表,设置回滚点,另一种是以Laravel为代表,控制事务数量。Doctrine的解决方案Doctrine的解决方案核心是对回滚点的控制,具体如下:Doctrine中开启事务的方法Doctrine中事务回滚的方法Doctrine中事务提交的方法Doctrine使用一个_transactionNestingLevel来标识当前的嵌套层级,如果为1,即没有嵌套,则使用默认方式执行STARTTRANSACTION就可以了;如果大于1,也就是有嵌套的时候,会帮我们创建保存点。这个保存点可以理解为一个事务记录点,只有需要回滚的时候我们才能回滚到这个点。与Doctrine相比,Laravel的解决方案要简单粗暴一点。它巧妙地使用了一个事务属性来记录事务被调用的次数。在事务启动、事务提交、事务回滚时,先判断事务的属性值,只有当事务的属性值为1时,才进行事务操作。如下:在开始事务的时候,我们先判断当前有多少个事务,如果是第一个,ok,事务开始,否则什么都不做。事务提交的时候,也会判断当前事务的个数。如果是第一个,ok,提交交易。否则,只有交易属性的值减一。事务回滚时,也是先判断当前事务的个数。如果是第一个,ok,回滚事务,并将事务属性值设置为0,否则,只将事务属性值减1。在Laravel的方案中,嵌套的内层其实并没有真正的事务,只有最外层的整体事务。虽然简单粗暴,但是也解决了在内层新建交易的问题。提交问题。