避免长事务性能瓶颈需收缩事务边界至必要DB写操作,剥离RPC、MQ等非DB操作;用TransactionTemplate替代@Transactional实现精准控制;强制设置超时与降级隔离级别;SELECT操作严禁入事务,只读接口标注readOnly=true。

避免长事务导致的性能瓶颈,核心是让事务只做最必要的事:仅包裹数据库写操作,其他一律剥离。事务不是“功能开关”,而是资源锁的持有期——越长,连接池越容易耗尽,死锁概率越高,数据库压力越大。
精准控制事务边界
事务范围必须收缩到“真正需要原子性保障”的几行 SQL 上:
- 把 RPC 调用、MQ 发送、Redis 操作、文件读写、复杂计算、日志同步等全部移出事务方法体
- 订单创建场景中,库存扣减 + 订单落库进事务;发券、通知、积分更新全部异步后置
- 用户注册流程里,仅用户表插入 + 配置初始化在事务内;欢迎邮件、ES 同步、风控校验走事务外补偿
用编程式事务替代 @Transactional
@Transactional 以整个方法为单位,一旦混入查询或远程调用,事务就必然膨胀。TransactionTemplate 可精确圈定执行段:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- queryUser(userId); // 事务外查缓存或 DB
- transactionTemplate.execute(status → { saveOrder(order); updateStock(itemId, -1); }); // 纯 DB 写
- sendOrderSuccessMQ(orderId); // 事务外发消息
强制设置超时与降级隔离级别
不设超时等于放任事务悬停,不降隔离级别等于主动制造锁竞争:
立即学习“Java免费学习笔记(深入)”;
- 声明式事务加 @Transactional(timeout = 30)(单位秒)
- JDBC URL 加 &socketTimeout=30000,防网络卡死
- MySQL 服务端配 idle_in_transaction_session_timeout = 30000,超时自动 kill
- 非强一致场景改用 READ_COMMITTED,避免间隙锁和锁升级
查询操作坚决不进事务
SELECT 不修改数据,不需要事务保证一致性,放进 @Transactional 只会无谓延长锁持有时间:
- 反模式:@Transactional 方法里先 select,再 insert,再 update
- 正确做法:select 提前到事务外;若需“读已提交”一致性,用 SELECT ... FOR UPDATE 显式加锁,且仅限真正需要的那一条语句
- 对只读接口,显式标注 @Transactional(readOnly = true),部分数据库可跳过 undo log 记录


















