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::beginTransac
tion()
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(...) 指定连接transaction() 不会新建事务,而是复用外层事务(底层依赖数据库是否支持 savepoint)DB::transactionLevel() 和 DB::rollBack(1)(慎用,可读性差)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']);
});
基本上就这些。用闭包方式最简洁可靠,手动控制只在特殊逻辑下需要。记住:事务不是万能的,它只保证数据库层面的一致性,不解决并发竞争(如超卖),必要时还需配合行锁或乐观锁。