Spring JPA插入随机挂起无限等待问题排查求助
排查思路
一、SQL Server锁与阻塞根源排查
- 问题复现时,立刻用
sp_who2、sys.dm_tran_locks、sys.dm_os_waiting_tasks查询阻塞链:确认插入操作的SPID持有锁的类型(如X锁、TABLOCK)、锁定资源(整张表还是特定行),以及它与存储过程会话的阻塞关系。 - 对比两次执行的SQL语句:开启Hibernate的
show_sql或logging.level.org.hibernate.SQL=DEBUG,检查移除健康数据场景下的插入语句是否未走主键索引,导致SQL Server升级锁粒度为表级锁。 - 查看存储过程执行计划:用
SET SHOWPLAN_XML ON或SSMS的「包括实际执行计划」,验证Customer_health_update在移除场景下是否存在锁升级、隐式事务残留等问题。
二、Hibernate事务与JDBC交互排查
- 确认
@Transactional的配置:检查隔离级别是否被修改为REPEATABLE_READ/SERIALIZABLE(默认是READ_COMMITTED),以及事务传播行为是否导致意外的嵌套事务,延长锁持有时间。 - 强制刷新并清理缓存:在插入健康数据后,执行
entityManager.flush()+entityManager.clear(),确保Hibernate缓存与数据库状态同步,避免缓存不一致引发的异常锁。 - 检查存储过程调用方式:确认调用SP时是否使用了与
@Transactional兼容的方式(如entityManager.createNativeQuery),有没有手动启停事务的代码导致冲突。
三、存储过程残留问题排查
- 重新核对SP代码:用
sp_helptext 'dbo.Customer_health_update'查看实际代码,确保没有遗漏的BEGIN TRANSACTION、COMMIT/ROLLBACK语句,也不存在SET IMPLICIT_TRANSACTIONS ON的隐式事务设置。 - 独立测试SP:在SSMS中模拟移除场景的参数,分别在事务内、事务外调用SP,看是否会出现锁等待,排除应用层的影响。例如:
BEGIN TRANSACTION -- 模拟移除健康数据后的插入操作 EXEC dbo.Customer_health_update @参数 COMMIT TRANSACTION
四、业务逻辑与数据一致性验证
- 检查移除场景的代码分支:确认是否存在“删除所有健康数据后又执行插入”的矛盾操作,或者插入的健康数据存在主键/唯一键异常(如空ID、重复ID)。
- 验证事务回滚逻辑:杀死卡住的SPID后事务自动回滚,但请求返回200且数据正确,说明移除场景下的插入操作可能是多余的,需确认业务流程是否存在分支错误。
五、补充日志与监控
- 开启SQL Server扩展事件:创建跟踪
lock_acquired、lock_wait、deadlock_graph的扩展事件会话,捕获数据库端的详细锁事件,比Hibernate日志更直接定位问题。 - 升级Hibernate日志级别:将
org.hibernate.type设为TRACE,查看插入语句的参数值,确认第二次插入的健康数据ID是否未生成或存在异常。
内容的提问来源于stack exchange,提问作者Nutan
相关产品推荐
相关产品推荐

