原因总结
- 在高并发的情况下,Spring事物造成数据库死锁,后续操作超时抛出异常。
- Mysql数据库采用InnoDB模式,默认参数:innodb_lock_wait_timeout设置锁等待的时间是50s,一旦数据库锁超过这个时间就会报错。
那么如何查看innodb_lock_wait_timeout的具体值:
SHOW VARIABLES LIKE 'innodb_lock_wait_timeout'
如何修改innode lock wait timeout的值,参数修改的范围有Session和Global,并且支持动态修改,默认是50s,可以有两种方法修改:
通过下面语句修改:
set innodb_lock_wait_timeout=100;
set global innodb_lock_wait_timeout=100;
ps. 注意global的修改对当前线程是不生效的,只有建立新的连接才生效。
方法二:
修改参数文件/etc/my.cnf
innodb_lock_wait_timeout = 50
ps. innodb_lock_wait_timeout
指的是事务等待获取资源等待的最长时间,超过这个时间还未分配到资源则会返回应用失败;当锁等待超过设置时间的时候,就会报如下的错误;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
。
其参数的时间单位是秒,最小可设置为1s(一般不会设置得这么小),最大可设置1073741824秒,默认安装时这个值是50s(默认参数设置)。
解决方法
- 应急方法:
show full processlist;
kill
掉出现问题的进程。ps.有的时候通过processlist是看不出哪里有锁等待的,当两个事务都在commit阶段是无法体现在processlist上 - 根治方法:
select * from information_schema.innodb_trx;
查看有是哪些事务占据了表资源。ps.通过这个办法就需要对innodb有一些了解才好处理 - 增加锁等待时间,即增大下面配置项参数值,单位为秒(s)
innodb_lock_wait_timeout=500
- 优化存储过程,事务避免过长时间的等待