最近遇到單條更新SQL語句一直報超時:
update where id=x
原因是有一個事務(wù),因為開發(fā)機器上不正常中斷程序,導(dǎo)致沒有提交洞拨。
先從mysql進(jìn)程下手
show full processlist;
或者
select * from information_schema.`PROCESSLIST` where db='xxx'
查看有沒有DEADLOCK 的進(jìn)程剧劝。
結(jié)果發(fā)現(xiàn)沒有一條記錄是DEADLOCK的雁芙。
(實際上有一個進(jìn)程顯示為SLEEP, 是其中一個一直沒有提交事務(wù)的進(jìn)程)
再從innodb狀態(tài)下手
可查看一共有多少個鎖在等待
show status like 'innodb%';
Innodb_row_lock_waits 表示正在等待的鎖
再再從innodb 狀態(tài)下手
show engine innodb status
配合表使用情況,掌握當(dāng)前鎖表情況
show open tables from xxx_db;
查看關(guān)于Innodb三張重要的表:
show tables from information_schema like 'INNODB%';
主要有三張表:
- INNODB_LOCKS
- INNODB_TRX
- INNODB_LOCK_WAITS
查看未提交的事務(wù)
查看具體事務(wù)列表
select * from information_schema.innodb_trx;
發(fā)現(xiàn)有一條記錄罐盔,有一個字段 tx_thread_id記錄著事務(wù)對應(yīng)的進(jìn)程id但绕。
回到show processlist;查看這個進(jìn)程id,發(fā)現(xiàn)顯示的狀態(tài)為SLEEP。
殺掉進(jìn)程:
kill {未提交事務(wù)對應(yīng)的進(jìn)程id}
最后更新語句正常執(zhí)行了。
備注
show processlist; 里顯示的進(jìn)程捏顺,雖然沒有顯示DEADLOCK六孵,
但不能證明要更新的id 沒有被獨占。
出現(xiàn)DEADLOCK 應(yīng)該是多個事務(wù)里互相請求 X鎖才會幅骄,而在這個情況只是一個事務(wù)一直沒有提交劫窒,而另外一個事務(wù)在請求X鎖,所以進(jìn)程顯示成了SLEEP拆座。
最后發(fā)現(xiàn)是有人在自己的開發(fā)機器上主巍,強行終端未提交事務(wù)的程序,導(dǎo)致連接斷開了挪凑,但事務(wù)一直在掛起孕索。