Mysql锁表异常原因以及解决

835 阅读2分钟

前言

在开发过程中遇到了一个奇怪的现象,项目编译部署不成功,然后报错:

Failure obtaining db row lock: Lock wait timeout exceeded; try restarting

报错的意思很明确,就是无法获得表的行锁并且超时了,尝试重启。

解决办法

出现锁表现象的解决办法就是将持有表锁的进程kill掉,释放表锁。具体操作如下:

SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX; //该命令用于查询当前运行的所有事务

从查询结果中可以找到是否有表锁处于等待或者死锁的状态,如果出现死锁,则可以通过kill 命令将进程杀死,释放锁资源。

kill trx_mysql_thread_id;

问题原因

由于mysql中InnoDB的delete、update、insert等操作是排他锁,会独占整个行直到用户退出数据库或者事务commit才会释放锁。因此,下面两种情况会出现行锁,导致上面的报错。

    1. A进程对i行执行insert操作,尚未提交时,B进程也对i行执行insert操作。
    1. A进程开启一个事务锁定了i行,尚未提交时,B进程也开启了一个事务去请求获取i行的锁。

死锁

当mysql使用事务的时候,很可能出现死锁现象导致上面的异常。死锁的发生一般是事务持有了一个行锁又去请求另一个行锁。如:

A进程开启了一个事务持有了i行的锁又去请求j行的锁,B进程此时也开启了一个事务持有j行的锁又去请求i行的锁。

此时,两个事务同时持有对方需要的行锁又不进行释放就会出现上述异常。

同样,对于需要锁表的操作而言也会出现类似问题,解决办法就是kill掉对应进程。