在代码debug模式中,调试业务流程时遇到
java.lang.Exception:
### Error updating database. Cause: java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction
异常;
原因分析: 执行update sql语句时发生 "LOCK WAIT”事务.
具体来说就是:
当事务A对记录1进行更新或者删除操作的请求未commit时,还处于debug调试中,另一个事务B(浏览器)也对记录1进行更新或者删除操作,此时事务B回等待前一个事务A提交事务,释放行锁,如果这个时间超过mysql设置的超时时间,则会产生“LOCK WAIT”事务。
解决办法:
执行mysql命令: SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;
找到 trx_state 为“LOCK WAIT”的记录,根据记录中查询语句的系统id(trx_mysql_thread_id):kill掉被锁住的线程id
KILL trx_mysql_thread_id ;
这是请求还会出现 "LOCL_WAIT"的情况;
在没有其他程序请求数据库时,执行mysql命令SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;
发现结果除了一条"LOCK_WAIT"的记录,还有两条对应的"RUNNING"记录,索性一次性全部都 kill 掉后。
问题解决了。
代码层修复:1.在有该sql的代码模块加入事物,并且指定超时时间;
@Transactional( rollbackFor = Exception.class , isolation = Isolation.REPEATABLE_READ, timeout = 30)
SQL优化:2、事务中 存在批量修改、删除的语句的时候,where 条件尽量加索引