MySQL - 一次锁表排查

最近遇到单条更新SQL语句一直报超时:

update where id=x

原因是有一个事务,因为开发机器上不正常中断程序,导致没有提交。

先从mysql进程下手

show full processlist;
或者
select * from information_schema.`PROCESSLIST` where db='xxx'

查看有没有DEADLOCK 的进程。
结果发现没有一条记录是DEADLOCK的。
(实际上有一个进程显示为SLEEP, 是其中一个一直没有提交事务的进程)

再从innodb状态下手

可查看一共有多少个锁在等待

show status like 'innodb%';
Innodb_row_lock_waits   表示正在等待的锁

再再从innodb 状态下手

show engine innodb status

配合表使用情况,掌握当前锁表情况

show open tables from xxx_db;

查看关于Innodb三张重要的表:

show tables from  information_schema like 'INNODB%';

主要有三张表:

  1. INNODB_LOCKS
  2. INNODB_TRX
  3. INNODB_LOCK_WAITS

查看未提交的事务

查看具体事务列表

select * from information_schema.innodb_trx;

发现有一条记录,有一个字段 tx_thread_id记录着事务对应的进程id。

回到show processlist;查看这个进程id,发现显示的状态为SLEEP。

杀掉进程:

kill {未提交事务对应的进程id}

最后更新语句正常执行了。

备注

show processlist; 里显示的进程,虽然没有显示DEADLOCK,
但不能证明要更新的id 没有被独占。
出现DEADLOCK 应该是多个事务里互相请求 X锁才会,而在这个情况只是一个事务一直没有提交,而另外一个事务在请求X锁,所以进程显示成了SLEEP。


最后发现是有人在自己的开发机器上,强行终端未提交事务的程序,导致连接断开了,但事务一直在挂起。

你可能感兴趣的:(MySQL - 一次锁表排查)