4.8 KiB
4.8 KiB
✅ 支付事务回滚问题修复完成
修复时间: 2026-01-25
问题: 订单支付时出现 "Transaction rolled back because it has been marked as rollback-only" 错误
🔍 问题分析
错误现象
支付失败: Transaction rolled back because it has been marked as rollback-only
根本原因
在 OrderServiceImpl.payOrder() 方法中,调用了 distributorService.createDistributorOrderFromOrder(order),该方法内部可能抛出异常,导致外层事务被标记为 rollback-only。
虽然代码中有 try-catch 包裹,但由于事务传播机制的问题,内部事务的异常仍然会影响外层事务。
🔧 修复方案
修复1:增强异常日志
在 OrderServiceImpl.payOrder() 中增加了更详细的日志输出:
// ✅ 新增:订单支付成功后,自动创建分销订单记录
// 🔥 修复:使用独立事务,避免影响主支付流程
try {
log.info("订单支付成功,开始创建分销订单记录...");
log.info("订单信息: orderId={}, userId={}, serviceId={}, serviceType={}, payAmount={}",
order.getId(), order.getUserId(), order.getServiceId(), order.getServiceType(), order.getPayAmount());
distributorService.createDistributorOrderFromOrder(order);
log.info("✅ 分销订单记录创建完成");
} catch (Exception e) {
log.error("❌ 创建分销订单记录失败: orderId={}, error={}", order.getId(), e.getMessage(), e);
// 🔥 关键:不影响支付流程,只记录错误
// 即使分销订单创建失败,支付也应该成功
}
修复2:使用独立事务(REQUIRES_NEW)
将 DistributorServiceImpl.createDistributorOrderFromOrder() 方法改为使用独立事务:
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
public void createDistributorOrderFromOrder(com.peidu.entity.Order order) {
log.info("=== 开始创建分销订单记录(独立事务) ===");
// ... 业务逻辑
}
关键点:
Propagation.REQUIRES_NEW会创建一个新的独立事务- 即使这个事务失败回滚,也不会影响外层的支付事务
- 外层的 try-catch 会捕获异常,但不会导致支付失败
修复3:添加必要的import
在 DistributorServiceImpl 中添加了缺失的import:
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
✅ 修复结果
编译状态
[INFO] BUILD SUCCESS
[INFO] Total time: 24.136 s
修改的文件
peidu/backend/src/main/java/com/peidu/service/impl/OrderServiceImpl.javapeidu/backend/src/main/java/com/peidu/service/impl/DistributorServiceImpl.java
🧪 测试步骤
1. 重启后端服务
# 停止当前运行的后端服务
# 重新启动后端服务
2. 测试支付功能
- 打开小程序,进入订单详情页面
- 点击"支付"按钮
- 选择支付方式(mock模拟支付)
- 观察支付结果
3. 预期结果
- ✅ 支付成功
- ✅ 订单状态更新为"已支付"
- ✅ 即使分销订单创建失败,支付也能成功
- ✅ 后端日志中会记录详细的支付流程信息
4. 查看后端日志
关注以下日志输出:
=== 开始处理支付 ===
订单ID: xxx
支付方式: mock
订单当前状态: 0
状态验证通过,开始更新订单
准备更新数据库...
数据库更新结果: true
支付成功,订单状态已更新为: 1
订单支付成功,开始创建分销订单记录...
订单信息: orderId=xxx, userId=xxx, serviceId=xxx, serviceType=xxx, payAmount=xxx
✅ 分销订单记录创建完成
=== 支付处理完成,返回结果: true ===
📝 技术说明
事务传播机制
REQUIRED(默认):
- 如果当前存在事务,加入该事务
- 如果内部方法抛出异常,会标记外层事务为 rollback-only
REQUIRES_NEW:
- 总是创建新事务
- 挂起当前事务(如果存在)
- 新事务独立提交或回滚,不影响外层事务
为什么这样修复有效?
- 独立事务隔离:分销订单创建使用独立事务,失败不影响支付
- 异常捕获:外层 try-catch 捕获异常,记录日志但不抛出
- 业务解耦:支付成功与否不依赖分销订单创建
🎯 后续优化建议
- 异步处理:将分销订单创建改为异步处理(使用消息队列)
- 重试机制:分销订单创建失败时,可以加入重试队列
- 监控告警:分销订单创建失败时发送告警通知
📌 注意事项
- 重启后端服务后才能生效
- 如果仍然失败,查看后端日志找出具体原因
- 分销订单创建失败不影响支付,但需要后续手动补偿
修复完成!请重启后端服务并测试。