前言
在开发过程中遇到了一个奇怪的现象,项目编译部署不成功,然后报错:
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才会释放锁。因此,下面两种情况会出现行锁,导致上面的报错。
-
- A进程对i行执行insert操作,尚未提交时,B进程也对i行执行insert操作。
-
- A进程开启一个事务锁定了i行,尚未提交时,B进程也开启了一个事务去请求获取i行的锁。
死锁
当mysql使用事务的时候,很可能出现死锁现象导致上面的异常。死锁的发生一般是事务持有了一个行锁又去请求另一个行锁。如:
A进程开启了一个事务持有了i行的锁又去请求j行的锁,B进程此时也开启了一个事务持有j行的锁又去请求i行的锁。
此时,两个事务同时持有对方需要的行锁又不进行释放就会出现上述异常。
同样,对于需要锁表的操作而言也会出现类似问题,解决办法就是kill掉对应进程。