06日1515-修复消耗组服务事务嵌套问题.md 3.5 KB

修复消耗组服务事务嵌套问题

任务时间

  • 开始时间:2025年06月06日 15:10:35 CST
  • 完成时间:2025年06月06日 15:15:15 CST

问题描述

用户报告 request_1749193224473 请求出现错误,通过日志分析发现是事务嵌套问题:

[2025-06-06T15:10:47.099459+08:00] laravel.ERROR: check_tr - transaction level >1 事务嵌套  [] [] []
[2025-06-06T15:10:47.115180+08:00] laravel.ERROR: 执行消耗失败 {"user_id":10006,"consume_group":31,"source":"开启宝箱","source_id":27,"error":"transaction level > 1"} []

问题分析

通过分析调用链发现事务嵌套的原因:

  1. OpenboxHandler 在第57行开启了事务 DB::beginTransaction()
  2. 然后调用 ChestService::openChest()
  3. ChestService::openChest() 调用 ConsumeService::executeConsume()
  4. ConsumeService::executeConsume() 在第127行又开启了一个事务 DB::beginTransaction()
  5. 最终在 ItemService::consumeItem() 中调用 Helper::check_tr() 检查事务状态
  6. 此时事务级别为2(嵌套事务),触发了 transaction level > 1 错误

解决方案

修改消耗组服务的事务管理策略,让调用者负责事务管理:

1. 修改 ConsumeService::executeConsume() 方法

  • 移除方法内部的事务管理(DB::beginTransaction()DB::commit()
  • 添加事务检查 \UCore\Db\Helper::check_tr() 确保调用者已开启事务
  • 移除异常处理中的事务回滚逻辑

2. 修改 executeCurrencyConsume() 方法

  • 移除内部事务管理
  • 添加事务检查
  • 移除异常处理中的事务回滚逻辑

3. 修改 executeFundConfigsConsume() 方法

  • 移除内部事务管理
  • 添加事务检查
  • 移除异常处理中的事务回滚逻辑

4. 移除不再使用的DB导入

  • use 语句中移除 Illuminate\Support\Facades\DB

修改的文件

  • app/Module/Game/Services/ConsumeService.php

验证结果

使用验证命令测试修复效果:

php artisan debug:reproduce-error request_1749193224473

修复前:

[2025-06-06T15:10:47.099459+08:00] laravel.ERROR: check_tr - transaction level >1 事务嵌套

修复后:

{
  "runUnid": "6842957cb4235",
  "runMs": "6093",
  "code": "OK",
  "callpath": "Item-Openbox",
  "deduct": {
    "items": [
      {"itemId": "2", "quantity": "500"},
      {"itemId": "3", "quantity": "500"},
      {"itemId": "27", "quantity": "1"}
    ]
  },
  "reward": {
    "items": [
      {"itemId": "2", "quantity": "1622"}
    ]
  }
}

技术要点

  1. 事务管理原则:避免嵌套事务,由最外层调用者负责事务管理
  2. 事务检查:使用 \UCore\Db\Helper::check_tr() 确保事务状态正确
  3. 错误处理:移除内层方法的事务回滚,让外层统一处理
  4. 代码清理:移除不再使用的导入语句

影响范围

  • 修复了宝箱开启功能的事务嵌套错误
  • 优化了消耗组服务的事务管理架构
  • 提高了系统的稳定性和可维护性

提交信息

修复消耗组服务事务嵌套问题

- 移除ConsumeService::executeConsume()方法中的事务管理
- 移除executeCurrencyConsume()和executeFundConfigsConsume()方法中的事务管理
- 添加事务检查,确保调用者已开启事务
- 修复宝箱开启时的'transaction level > 1'错误
- 所有事务管理现在由调用者(如ChestService::openChest)负责

总结

成功修复了消耗组服务中的事务嵌套问题,通过重构事务管理策略,确保了系统的稳定性。修复后宝箱开启功能正常工作,没有任何错误日志。