从Laravel,Yii,Thinkphp中学习php 操作数据库的事务嵌套

Posted 写PHP的老王

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从Laravel,Yii,Thinkphp中学习php 操作数据库的事务嵌套相关的知识,希望对你有一定的参考价值。

最近维护历史代码,使用的是phalapi 最初版本开发,数据库操作使用的是notorm。notorm本身不支持事务嵌套,但是在开发过程中,多个操作进行拆分,根据不同业务不同进行调用,必然会设计到多个事务嵌套在一起的问题。举个栗子:

1) 公共模块A,更新用户的账户余额,添加流水记录操作。
2) 模块B,根据用户的操作(消费或充值)根据活动配置赠送相应的优惠券。
基础业务A模块就够用了,但是出现一些业务活动的时候,需要在A成功之后调用B模块,只有两个操作成功之后才完整提交事务。要实现这样的功能,无非两种方式:

1) 模块内部不加事务,事务控制统一交给调用方。谁调用,谁负责事务。内部模块只提供内部模块执行结果。
2) 模块内部控制事务,外部调用只需知道内部执行是否成功。

如果设计的合理,还是比较倾向于使用第一种方案。但是不可否认,你无法确定你的调用模块会不会再被其他人调用,最终结果又演变成第二种方案。因此底层还是需要支持事务嵌套。

嵌套事务的核心思想就是添加一个计数器,第一次开启事务,最后一次提交或回滚执行数据库操作,其他情况只是更新计数器数值。分别看一看几个现有框架如何设计数据库事务嵌套操作:

1) Laravel
Laravel与事务相关操作封装在 Illuminate\Database\Concerns\ManagesTransactions当中。

2) Yii2

Yii2的事务操作也是有一个单独文件进行封装,yii\db\Transaction。

从Laravel,Yii,Thinkphp中学习php 操作数据库的事务嵌套

3) Thinkphp5

Thinkphp5的事务操作并没有独立分开,直接在数据库连接类当中think\db\Connection;

三个框架都是通过计数器以及数据库本身的"部分事务"支持嵌套事务的操作。mysql 中通过 savepoint 的方式来实现只提交事务的一部分。操作流程大体分一下三步
1) 开启事务,检查计数器是否是第一次开启,如果是则执行pdo开启事务,不是则修改计数器的值,同时根据是否支持部分事务,执行pdo savepoint操作。
2) 事务提交,检查计数器是否是最外层事务,是则执行pdo事务提交操作,否则计数器减1
3) 事务回滚,检查计算器是否是最外层操作,是则执行pdo事务回滚,否则计数器减1,同时根据是否支持部分事务,执行pdo rollbak to savepoint 操作

虽然整体思路一样,但是三个框架根据自身的特定,代码设计抽象程度不一样。从这个相同的功能,也能够很好的体会三个框架不同的设计方式。


以上是关于从Laravel,Yii,Thinkphp中学习php 操作数据库的事务嵌套的主要内容,如果未能解决你的问题,请参考以下文章

当我在 laravel 中学习 http 客户端时,我在浏览器中收到此错误“ErrorException Trying to access array offset on value of type

C++ (tensorRT中学习)

从题目中学习java语法

markdown 从基本粪便中学习语法[第1部分]

从kata中学习编程

从别人的代码中学习golang系列--01