以下工具类库,默认基于laravel框架
开始开发前,每个项目参与者都必须对laravel、dcat中的一些模块或概念有个基本的认识。否则将无法有效提供AI提示词,则无法加快研发效率。 要求每个人在业余时间对官方文档提供的每一个功能点,做一个开发和测试,这样建立基本的认识。
串行化 (SERIALIZABLE):适用于需要严格事务隔离的场景,例如银行转账,确保事务完全隔离,避免所有并发问题,但可能会影响性能。
可重复读 (REPEATABLE READ):适用于需要保证在同一事务中多次读取同一数据的一致性的场景,例如库存查询和减少操作,避免在事务过程中数据被其他事务修改。
读已提交 (READ COMMITTED):适用于大多数需要避免脏读的场景,每次读取都能看到其他事务的最新提交结果,但可能会出现不可重复读和幻读。
读未提交 (READ UNCOMMITTED):适用于读操作对数据一致性要求不高的场景,允许读取到其他事务未提交的数据,可能会导致脏读、不可重复读和幻读。
// 串行化 (SERIALIZABLE) - 最严格的隔离级别,完全隔离,事务串行执行
use Illuminate\Support\Facades\DB;
DB::transaction(function () {
// 操作1:读取用户A的当前余额
$balanceA = DB::table('accounts')->where('user_id', $userIdA)->value('balance');
// 操作2:减少用户A的余额
DB::table('accounts')->where('user_id', $userIdA)->decrement('balance', $amount);
// 操作3:增加用户B的余额
DB::table('accounts')->where('user_id', $userIdB)->increment('balance', $amount);
}, DB::TRANSACTION_SERIALIZABLE);
// 可重复读 (REPEATABLE READ) - 保证事务中每次读取结果都相同,避免不可重复读和脏读
use Illuminate\Support\Facades\DB;
DB::transaction(function () {
}, DB::TRANSACTION_REPEATABLE_READ);
// 读已提交 (READ COMMITTED) - 每次读取只能看到其他事务已经提交的数据,避免脏读
use Illuminate\Support\Facades\DB;
DB::transaction(function () {
}, DB::TRANSACTION_READ_COMMITTED);
// 读未提交 (READ UNCOMMITTED) - 最宽松的隔离级别,可能会读取到其他事务未提交的数据(脏读)
use Illuminate\Support\Facades\DB;
DB::transaction(function () {
}, DB::TRANSACTION_READ_UNCOMMITTED);
在 Laravel 中,如果你在一个 DB::transaction 回调中调用另一个也使用 DB::transaction 的方法,将会出现以下情况:
嵌套事务:Laravel 支持嵌套事务。当你在事务中调用另一个事务时,Laravel 会使用保存点(Savepoints)来处理嵌套的事务。保存点允许你在事务中设置一个点,之后可以回滚到这个点,而不影响事务中之前的操作。
保存点的创建:对于每个嵌套的事务,Laravel 会创建一个保存点。如果内部事务成功提交,保存点会被释放;如果内部事务失败并回滚,只有内部事务的更改会被回滚到保存点,外部事务的其他操作不受影响。
事务的回滚:如果内部事务中抛出异常,整个内部事务会被回滚到最近的保存点。如果外部事务中抛出异常,整个外部事务(包括所有内部事务)会被回滚。
下面是一个示例,说明这种情况:
use Illuminate\Support\Facades\DB;
DB::transaction(function () {
// 外部事务开始
// 一些数据库操作
DB::table('accounts')->insert([...]);
$this->nestedTransaction(); // 调用包含内部事务的方法
// 更多数据库操作
DB::table('accounts')->update([...]);
}, DB::TRANSACTION_SERIALIZABLE);
// 包含内部事务的方法
protected function nestedTransaction()
{
DB::transaction(function () {
// 内部事务开始
// 一些数据库操作
DB::table('accounts')->insert([...]);
// 假设这里发生了错误,内部事务会回滚
throw new Exception('Something went wrong!');
// 更多数据库操作,如果内部事务成功,这些操作会执行
DB::table('accounts')->update([...]);
}, DB::TRANSACTION_SERIALIZABLE);
}
在这个例子中,如果 nestedTransaction 方法中的内部事务因为抛出异常而失败,只有内部事务中的操作会被回滚。外部事务中的操作(在调用 nestedTransaction 之前和之后的操作)不会受到影响,除非外部事务本身抛出异常。