一、查看 InnoDB 事務(wù)及鎖狀
-- 查看所有活躍事務(wù)(含鎖信息)
SELECT
trx_id, -- 事務(wù)ID
trx_state, -- 事務(wù)狀態(tài)(RUNNING/LOCK WAIT等)
trx_started, -- 事務(wù)啟動(dòng)時(shí)間
trx_mysql_thread_id, -- 線程ID
trx_query, -- 事務(wù)執(zhí)行的SQL
trx_wait_started, -- 開始等待鎖的時(shí)間
trx_lock_structs -- 事務(wù)持有的鎖數(shù)量
FROM
information_schema.innodb_trx
WHERE
trx_state != 'COMMITTED'; -- 過濾已提交的事務(wù)
二、定位阻塞該事務(wù)的 “元兇”
執(zhí)行以下 SQL,找到持有鎖并阻塞當(dāng)前事務(wù)的線程 ID 和 SQL:
-- 關(guān)聯(lián)查詢阻塞者信息
SELECT
b.trx_id AS blocking_trx_id, -- 阻塞事務(wù)ID
b.trx_mysql_thread_id AS blocking_thread_id, -- 阻塞線程ID(關(guān)鍵)
b.trx_query AS blocking_sql, -- 阻塞者執(zhí)行的SQL
b.trx_started AS blocking_trx_started, -- 阻塞事務(wù)啟動(dòng)時(shí)間
TIMESTAMPDIFF(SECOND, b.trx_started, NOW()) AS blocking_trx_running_seconds -- 阻塞事務(wù)運(yùn)行時(shí)長(zhǎng)
FROM
information_schema.innodb_lock_waits w
JOIN
information_schema.innodb_trx b ON w.blocking_trx_id = b.trx_id
JOIN
information_schema.innodb_trx r ON w.requesting_trx_id = r.trx_id
WHERE
r.trx_id = '16933311'; -- 替換為你的等待事務(wù)ID
三、kill 阻塞線程
-- 替換為步驟二中查到的blocking_thread_id。假設(shè)阻塞線程ID是123
KILL 123;
四、檢查是否有長(zhǎng)事務(wù)持有鎖, 如果有可以直接kill全部阻塞線程
SELECT
trx_id,
trx_mysql_thread_id,
trx_query,
TIMESTAMPDIFF(SECOND, trx_started, NOW()) AS running_seconds
FROM
information_schema.innodb_trx
WHERE
TIMESTAMPDIFF(SECOND, trx_started, NOW()) > 60
ORDER BY running_seconds DESC;
五、開啟SQL語(yǔ)句執(zhí)行記錄日志,并輸出到文件
-- 開啟
SET GLOBAL log_output = 'file';SET GLOBAL general_log = 'ON';
-- 查詢?nèi)罩疚募恢?show variables like 'general_log_file';
-- 關(guān)閉
SET GLOBAL log_output = 'file';SET GLOBAL general_log = 'OFF';
truncate table mysql.general_log;