最近遇到单条更新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%';
主要有三张表:
- INNODB_LOCKS
- INNODB_TRX
- 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。
最后发现是有人在自己的开发机器上,强行终端未提交事务的程序,导致连接断开了,但事务一直在挂起。