在 MySQL 中查看事務鎖(鎖等待、鎖持有等),可以使用以下方法:
一、查看當前鎖等待情況(推薦)
SELECTr.trx_id AS waiting_trx_id,r.trx_mysql_thread_id AS waiting_thread,r.trx_query AS waiting_query,b.trx_id AS blocking_trx_id,b.trx_mysql_thread_id AS blocking_thread,b.trx_query AS blocking_query
FROMinformation_schema.innodb_lock_waits wJOIN information_schema.innodb_trx b ON b.trx_id = w.blocking_trx_idJOIN information_schema.innodb_trx r ON r.trx_id = w.requesting_trx_id;
此語句會顯示哪些事務在等待鎖,哪些事務持有鎖,方便定位阻塞。
二、查看當前持有鎖的事務
SELECT * FROM information_schema.innodb_trx;
字段說明:
trx_id:事務ID
trx_state:事務狀態(如:RUNNING、LOCK WAIT等)
trx_started:事務開始時間
trx_mysql_thread_id:線程ID
trx_query:正在執行的SQL語句
三、查看當前鎖的具體對象
SELECT * FROM information_schema.innodb_locks;
字段包括:
lock_id
lock_mode(鎖模式,e.g. S, X)
lock_type(類型:RECORD, TABLE)
lock_table
lock_index
lock_data(鎖定的主鍵信息)
四、組合查看完整鎖信息(更詳細)
SELECTr.trx_id AS waiting_trx_id,r.trx_mysql_thread_id AS waiting_thread,r.trx_query AS waiting_query,b.trx_id AS blocking_trx_id,b.trx_mysql_thread_id AS blocking_thread,b.trx_query AS blocking_query,l.lock_table,l.lock_index,l.lock_mode
FROMinformation_schema.innodb_lock_waits wJOIN information_schema.innodb_trx r ON w.requesting_trx_id = r.trx_idJOIN information_schema.innodb_trx b ON w.blocking_trx_id = b.trx_idJOIN information_schema.innodb_locks l ON l.lock_id = w.requested_lock_id;
可以在上面查詢結果基礎上,使用如下 SQL 自動生成 KILL 語句:
SELECTCONCAT('KILL ', r.trx_mysql_thread_id, ';') AS kill_command
FROMinformation_schema.innodb_lock_waits wJOIN information_schema.innodb_trx r ON w.requesting_trx_id = r.trx_id;
?? 這只會 KILL 處于等待狀態的線程,不會殺掉持鎖線程(即“元兇”線程)。
如果想殺掉 持鎖線程(阻塞源),執行如下SQL:
SELECTCONCAT('KILL ', b.trx_mysql_thread_id, ';') AS kill_command
FROMinformation_schema.innodb_lock_waits wJOIN information_schema.innodb_trx b ON w.blocking_trx_id = b.trx_id;
?? 殺掉持鎖事務可能會終止正在執行的寫操作,請務必確認!
示例輸出:
KILL 12345;
KILL 12346;
或通過如下SQL生成 KILL 阻塞線程語句:
SELECT CONCAT('KILL ', b.trx_mysql_thread_id, ';') AS kill_statement
FROM information_schema.innodb_lock_waits wJOIN information_schema.innodb_trx r ON w.requesting_trx_id = r.trx_idJOIN information_schema.innodb_trx b ON w.blocking_trx_id = b.trx_idJOIN information_schema.innodb_locks l ON l.lock_id = w.requested_lock_id;
有些鎖可能是短暫的,所以可加條件排除系統或空查詢:
WHERE b.trx_query IS NOT NULL AND b.trx_started < NOW() - INTERVAL 10 SECOND
只 Kill 執行時間超過 10 秒的阻塞事務。
?? Kill 需謹慎, Kill 前請確認是否可以 Kill。