解决事务锁问题:SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded; try restarting transaction
这个错误表明在执行一个事务时,等待锁定的时间超出了预设的超时时间,导致事务无法完成。在数据库中,当一个事务试图锁定一个资源(如一行数据、一个表)时,如果其他事务已经持有了该资源的锁,并且持有时间过长,那么当前事务就会等待一段时间来获取这个资源的锁。这是脚本的大概代码 ,刚好头条渠道由于密码修改,导致api报错,return 返回了错误信息,但是事务开启了,没有回滚或提交,但脚本进程执行又比较久,就
需求背景:
用thinkphp5.1在crontab定时任务抓取多个广告渠道的消耗数据,我这里写了一个定时脚本,脚本正常在跑是没问题的,有一天运营人员改了某个渠道的密码,导致某个渠道的api接口请求返回失败,然后系统触发监控预警信息:SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded; try restarting transaction。
问题猜测:
这个错误表明在执行一个事务时,等待锁定的时间超出了预设的超时时间,导致事务无法完成。在数据库中,当一个事务试图锁定一个资源(如一行数据、一个表)时,如果其他事务已经持有了该资源的锁,并且持有时间过长,那么当前事务就会等待一段时间来获取这个资源的锁。如果等待时间超出了系统设置的最大等待时间,就会出现这个错误。
一般情况下,这个错误可能是由以下原因引起的:
-
锁竞争:多个事务同时试图修改相同的数据,导致其中一个事务需要等待其他事务释放锁定的资源。
-
长时间运行的事务:某个事务占用了某些资源并且长时间不释放,导致其他事务无法获取资源的锁。
-
死锁:多个事务之间互相持有资源的锁,并且互相等待对方释放锁,最终导致所有事务都无法继续执行。
问题排查:
先查看当前MySQL连接线程,执行了发现没什么异常的信息
show full processlist
查看当前数据库运动的所有事务,执行了发现有一条事务在跑,但看不到具体的sql语句,如下图
select * from information_schema.innodb_trx
查看是否锁表,执行发现表不存在,可以排除是锁的问题
select * from information_schema.innodb_locks ## 当前出现的锁
select * from information_schema.innodb_lock_waits ## 锁等待的对应关系
由于当时脚本跑的时间比较长,调试执行MySQL的update和delete操作都会失败,报:SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded; try restarting transaction。直到脚本跑完后,就恢复正常了,而且执行:SELECT * FROM information_schema.innodb_trx;发现事务也不见了。所以问题有可能是问题猜测的第2点“长时间运行的事务”导致的。
解决问题:
这是脚本的大概代码 ,刚好头条渠道由于密码修改,导致api报错,return 返回了错误信息,但是事务开启了,没有回滚或提交,但脚本进程执行又比较久,就导致线上涉及到相关的数据表更新操作都会报错事务等待超时,只要在return 前面加上事务回滚,Db::rollback();问题即可解决。
更多推荐
所有评论(0)