数据库报错: java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction问题定位排查
对于数据库抛错Cause: java.sql.SQLException: (conn=7171207) Lock wait timeout exceeded; try restarting transaction,建议再三检查代码,仔细查看日志打印,定位是否某个耗时操作影响大事务提交。
遇到抛错如下:
用户反馈业务异常,查询日志发现有大量的sql:Lock wait timeout exceeded; try restarting transaction 异常错误日志打印。
问题原因分析:
Lock wait timeout exceeded; try restarting transaction 为数据库抛错信息,根本原因由于前一个事务更新了表的单条记录或者锁表更新未及时提交,导致后面的线程事务更新表或单条记录获取更新锁阻塞超时,抛错。、
注: mysql 获取写锁(X 锁)默认超时时间为50s
代码逻辑错误根因:
经过代码走读和日志排查发现,业务代码 A 线程使用spring 大事务中循环更新单表多条记录,而后每次调用第三方接口,由于响应慢,大事务迟迟不能提交,而同时有业务并发B线程异步更新同表的记录,B等待 A提交事务超过 50s ,导致mysql 抛错,业务异常中断。
解决:
取消大事务,在业务代码A 中循环中使用小粒度事务或者不使用事务。(合理使用事务)
总结:
事务很多时候给我们带来好处,比如数据一致性等。但不合理的使用事务可能潜藏隐患,尤其是并发接口响应慢等场景中断业务。建议:事务范围尽量缩小,使用消息队列等方式瘦身大事务。