Laravel 中 DB::transaction() 方法可自动处理事务提交与回滚,推荐使用闭包方式:闭包正常结束则自动提交,抛出异常则自动回滚;支持 Eloquent 操作、多连接指定及手动控制(beginTransaction/commit/rollback),但不支持真正嵌套事务。

在 Laravel 中,使用 DB Facade 实现数据库事务非常简单,核心是 DB::transaction() 方法,它会自动处理提交与回滚,无需手动调用 commit() 或 rollback()。
基本用法:闭包方式(推荐)
最常用、最安全的方式是把需要原子执行的数据库操作写在闭包里。只要闭包中抛出异常(包括验证失败、逻辑错误、数据库约束冲突等),事务就会自动回滚。
- 闭包内所有查询都在同一事务中执行
- 闭包正常结束 → 自动提交
- 闭包内抛出
Exception或Throwable→ 自动回滚
示例:
use Illuminate\Support\Facades\DB;
DB::transaction(function () {
DB::table('users')->update(['votes' => 1]);
DB::table('posts')->insert([
'title' => 'My first post',
'user_id' => 1
]);
// 如果这里抛出异常(比如字段超长、外键不存在),上面的 update 也会被撤销
throw new \Exception('模拟失败');
});
手动控制事务(较少用,但需了解)
当需要更精细的控制(比如条件性提交、嵌套判断、或在闭包外捕获异常做自定义处理)时,可用手动方式:
- 先调用
DB::beginTransaction() - 执行操作,检查结果
- 成功则
DB::commit(),失败则DB::rollback()
示例:
DB::beginTransaction();
try {
DB::table('users')->decrement('balance', 100);
DB::table('transactions')->insert(['amount' => -100, 'user_id' => 1]);
DB::commit();
} catch (\Exception $e) {
DB::rollback();
throw $e;
}
注意嵌套事务和连接配置
Laravel 的事务默认作用于当前数据库连接(通常是 default 连接)。如果应用配置了多个数据库连接,需显式指定:
- 用
DB::connection('mysql2')->transaction(...)指定连接 - Laravel 不支持真正的嵌套事务;重复调用
transaction()不会新建事务,而是复用外层事务(底层依赖数据库是否支持 savepoint) - 若需部分回滚,可手动使用
DB::transactionLevel()和DB::rollBack(1)(慎用,可读性差)
结合 Eloquent 使用同样有效
DB::transaction() 对 Eloquent 操作完全兼容,因为 Eloquent 底层也走的是同一个数据库连接:
- 模型的
save()、delete()、update()等都会纳入事务 - 关联操作(如
$user->posts()->create(...))也受保护
示例:
DB::transaction(function () {
$user = User::find(1);
$user->balance -= 50;
$user->save();
$user->posts()->create(['title' => 'New post']);
});
基本上就这些。用闭包方式最简洁可靠,手动控制只在特殊逻辑下需要。记住:事务不是万能的,它只保证数据库层面的一致性,不解决并发竞争(如超卖),必要时还需配合行锁或乐观锁。










