Laravel多租户创建时调用DB::beginTransaction报无活跃事务错误
解决Tenancy for Laravel创建租户时事务报错"There is no active transaction"
问题场景
使用Tenancy for Laravel创建新租户时,尝试通过手动事务或闭包事务包裹创建逻辑,触发错误:
There is no active transaction
仅在创建租户时出现该错误,更新租户时无异常。使用的两种事务写法均失效:
手动事务写法
try { DB::beginTransaction(); $tenant = $tenant->create($request->data); $tenant->domains()->create(['domain' => $request->domain.config('constants.domain_suffix')]); DB::commit(); } catch(\Exception $e) { DB::rollback(); return redirect()->back()->withErrors(__($e->getMessage()))->withInput(); }
闭包事务写法
DB::transaction(function () use ($request, &$tenant) { $tenant->create($request->data); $tenant->domains()->create(['domain' => $request->domain.config('constants.domain_suffix')]); });
问题原因
Tenancy for Laravel创建租户时,核心操作(如写入中央租户表)针对的是系统中央数据库,而默认的DB facade可能在创建租户过程中自动切换了数据库连接,导致外层事务绑定的连接失效;另外部分版本的Tenancy包在create方法内部已包含事务逻辑,外层事务嵌套触发冲突。
解决方案
1. 指定中央数据库连接执行事务
明确使用中央数据库连接来开启、提交/回滚事务,确保事务绑定到正确的数据库连接:
修正手动事务代码
try { // 替换为你的中央数据库连接名,默认可能是mysql $centralConnection = DB::connection('central'); $centralConnection->beginTransaction(); $tenant = $tenant->create($request->data); $tenant->domains()->create(['domain' => $request->domain . config('constants.domain_suffix')]); $centralConnection->commit(); } catch(\Exception $e) { // 确保回滚时连接存在且处于事务中 if(isset($centralConnection) && $centralConnection->getPdo()->inTransaction()) { $centralConnection->rollback(); } return redirect()->back()->withErrors(__($e->getMessage()))->withInput(); }
修正闭包事务代码
// 同样指定中央连接 DB::connection('central')->transaction(function () use ($request, &$tenant) { $tenant = $tenant->create($request->data); $tenant->domains()->create(['domain' => $request->domain . config('constants.domain_suffix')]); });
2. 排查模型事件干扰
检查租户模型(Tenant)或域名模型(Domain)的creating/created等事件监听器,确认这些事件中没有执行自动提交事务、切换数据库连接的操作,避免破坏外层事务。
3. 确认连接配置
确保config/database.php中配置了正确的中央数据库连接,若你的中央数据库使用默认mysql连接,将上述代码中的central替换为mysql即可。
内容的提问来源于stack exchange,提问作者Mukesh Khatri
相关产品推荐
相关产品推荐

