MySQL锁表问题

今天遇到一个情况,一条SQL语句执行提示如下异常。

Lock wait timeout exceeded; try restarting transaction

翻译一下是说,获取锁超时,尝试重新启动事务。翻译一下就是当我们申请对表进行加锁时,另外一个事务已经对这个表加了锁,经过一段时间等待后,我们的事务依然没有获取到锁,所以提示超时了。如果稍后重试可以成功,说明我们的数据库设置的超时参数可能太短了,结合我们的业务我们可以调整数据库参数。如果重试后依然不行,很可能是大事务将表锁了,这个时候,我们需要从两方面解决问题,一方面需要优化大事务或者添加告警机制,另一方面需要手动终止这个大事务,解除表锁。

以下仅描述解锁过程,大事务优化暂且不表。

连接数据库

数据库是主备模式,同时配置了VIP,需要先查询下数据库的实际IP,确定主节点IP,然后通过数据库工具或者命令行连接主节点实例。

查找锁并解除锁

通过如下命令查找正在执行的进程,从中可以看到有一个进程执行了超过12000s,即已经执行数日还没结束,判断该进程就是执行异常锁表的进程,使用kill命令终止这个锁表进程。

show processlist;
kill 锁表进程id;

执行kill命令后,可以看到执行异常导致锁表的进程Command变成了Killed.

大功告成?

NO,该进程只是被标记为Killed状态,但是依然在执行,如果是大事务导致的,则在执行回滚动作,待回滚结束才是真的结束,所以需要耐心等待,等这个进程不再出现在processlist列表中,则该进程被成功终止。

如果你拥有PROCESS权限,则可以通过下面的SQL来查看这个大事务的状态。

SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;

待锁表的进程被终止后,可以通过下面的语句查看目前被使用的表,in_use表示有多少线程正在使用该表。

show open tables where in_use > 0;
posted @ 2023-10-16 15:18  相由心生,命由己造  阅读(39)  评论(0编辑  收藏  举报