在 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。