MySQL如何查询被锁定的表?

来源:Vuejs社区作者:IT小魔仙头衔:程序员
导读:本期聚焦于IT小魔仙创作的《MySQL如何查询被锁定的表?》,敬请观看详情。排查 MySQL 锁表问题时,最怕只看到慢查询却看不到背后是谁持有锁。实际上 MySQL 8.0 的 performance_schema 和 sys 库已经把行锁、间隙锁、元数据锁的持有与等待关系记录得非常清楚,关键在于用对视图。本文从锁类型讲起,介绍 data_locks、data_lock_waits、metadata_locks、innodb_trx 和 sys.innodb_lock_waits 的用途,再结合 SHOW PROCESSLIST 给出完整排查路径。当一条 UPDATE 长时间没有提交,或者 ALTER TABLE 始终无法完成时,通过这些视图可以快速定位到阻塞事务的线程 ID、SQL 文本以及被锁定的表名,再决定是否需要 KILL 阻塞会话。文章也补充了常见误判场景,比如元数据锁等待和行锁等待的表现差异,避免盲目杀掉正常查询。

当业务高峰出现大量连接堆积、SQL 执行时间突然拉长时,多数情况下不是 SQL 本身变慢,而是目标表或目标行被其他事务锁住了。MySQL 并没有提供一条类似 SHOW LOCKED TABLES 的单命令,但通过 performance_schema、sys 和 information_schema 的组合查询,可以非常精确地看到锁持有者、等待者和被锁定的表名。实际排查时,需要先理清不同锁类型在元数据视图中的分布,再使用对应的查询语句。

MySQL如何查询被锁定的表?

先理清 MySQL 的锁类型与对应数据来源

MySQL 中的锁并不只有行锁。按粒度可以分为表锁、行锁和页锁;按用途可以分为共享锁、排他锁、意向锁;此外还有 DDL 与 DML 之间互相阻塞的元数据锁 MDL。不同类型的信息分散在不同的系统视图里,如果一开始就用错视图,很容易查了半天也找不到阻塞源头。

performance_schema.data_locks 用来记录 InnoDB 事务级别的行锁和意向锁信息,performance_schema.metadata_locks 用来记录元数据锁信息,information_schema.innodb_trx 则记录每个活跃事务的基本情况,而 sys.innodb_lock_waits 是官方封装好的视图,会把锁等待关系整理成更容易阅读的结果。

在 MySQL 5.7 或更早版本中,performance_schema 相关的锁等待消费者可能没有默认开启,需要确认 setup_consumers 中相关配置是否启用。对于 MySQL 8.0 来说,绝大多数情况下这些视图已经可以直接查询,不需要额外调整。

通过 performance_schema.data_locks 查看被锁定的表

要查行锁到底锁在哪些表上,最直接的方式是查询 performance_schema.data_locks。这个视图里有一个 OBJECT_NAME 字段,对应被锁定的表名;LOCK_TYPE 可以区分表级锁和行级锁,LOCK_MODE 则会显示 IX、X、S 等锁模式,LOCK_STATUS 用于判断锁是已经被授予还是正在等待。

SELECT
  engine,
  object_schema,
  object_name,
  lock_type,
  lock_mode,
  lock_status,
  lock_data
FROM performance_schema.data_locks;

如果查询结果中同一张表同时出现了 GRANTED 状态的 X 锁和另一个 WAITING 状态的 X 锁,就说明这里有明确的锁等待关系。此时你已经知道了被锁定的表名,但还需要继续定位哪个会话在等待、哪个会话在阻塞。可以继续查询 data_lock_waits 获取事务 ID 之间的等待关系。

SELECT
  requesting_engine_transaction_id AS waiting_trx,
  blocking_engine_transaction_id AS blocking_trx,
  requesting_engine_lock_id AS waiting_lock,
  blocking_engine_lock_id AS blocking_lock
FROM performance_schema.data_lock_waits;

拿到事务 ID 之后,还需要回到 data_locks 或 innodb_trx 里继续关联线程 ID 和 SQL 文本。这个过程比较繁琐,更适合在需要分析锁的具体类型和加锁范围时使用。如果只是想快速定位是哪个会话阻塞了业务,使用 sys.innodb_lock_waits 会高效得多。

使用 sys.innodb_lock_waits 快速定位阻塞会话

手动关联 data_locks 和 data_lock_waits 虽然完整,但字段多、步骤多。sys 库里的 innodb_lock_waits 视图已经把这些信息做了串联,直接展示等待事务 ID、阻塞事务 ID、等待的线程号、阻塞的线程号以及对应的 SQL 文本。

SELECT
  waiting_trx_id,
  waiting_pid,
  waiting_query,
  blocking_trx_id,
  blocking_pid,
  blocking_query,
  wait_age
FROM sys.innodb_lock_waits;

查询结果中,waiting_pid 是等待锁的线程号,blocking_pid 是持有锁的线程号。waiting_query 和 blocking_query 通常会展示正在执行或最后执行的 SQL,这对判断业务逻辑非常有帮助。拿到 blocking_pid 后,可以回到 information_schema.processlist 查看这个线程已经运行了多久、当前处于什么状态。

SELECT id, user, host, db, command, time, state, info
FROM information_schema.processlist
WHERE id = 123;

使用时把 123 替换成实际的 blocking_pid。如果发现这个线程是一个长时间未提交的空闲事务,或者是一条执行很久的大事务,就需要评估是否要 KILL 掉它。需要注意的是,KILL 会回滚该事务已经执行过的修改,在高并发业务中必须谨慎操作,最好先与相关业务方确认。

元数据锁造成的 ALTER TABLE 长时间无响应

除了 InnoDB 行锁,还有一种常见场景是 ALTER TABLE 长时间无法完成,线程状态一直显示为 Waiting for table metadata lock。这通常不是行锁问题,而是元数据锁 MDL 导致的。DDL 语句需要获取表级排他元数据锁,只要这张表上还有未提交的事务,DDL 请求就只能排队等待。

要定位这类问题,可以查询 performance_schema.metadata_locks,重点看 lock_status 为 PENDING 的记录,这些就是正在等待元数据锁的线程。

SELECT
  object_schema,
  object_name,
  lock_type,
  lock_status,
  owner_thread_id
FROM performance_schema.metadata_locks
WHERE object_type = 'TABLE'
  AND lock_status = 'PENDING';

有时候这个查询结果为空,可能是因为 performance_schema 的元数据锁 instrument 没有启用。此时可以检查 setup_consumers 中与 wait/lock/metadata/sql/mdl 相关的配置。更直接的兜底方式是执行 SHOW FULL PROCESSLIST,找到状态为 Waiting for table metadata lock 的线程,再回到同一张表上排查是否存在长时间未提交的事务。

SHOW PROCESSLIST 与 innodb_trx 配合排查

如果前面的视图因为权限不足或版本限制无法使用,SHOW FULL PROCESSLIST 是最基础的排查工具。关注 State 列中包含 lock 的记录,例如 Waiting for table metadata lock、Waiting for global read lock,以及 Updating 状态且耗时异常长的线程。Info 列会展示 SQL 文本,Id 列就是线程 ID。

SHOW FULL PROCESSLIST;

与此同时,可以查询 information_schema.innodb_trx 查看当前所有活跃事务,通过事务开始时间和锁定的行数来判断哪个事务最可疑。

SELECT
  trx_id,
  trx_state,
  trx_started,
  trx_mysql_thread_id,
  trx_query,
  trx_rows_locked,
  trx_rows_modified
FROM information_schema.innodb_trx
ORDER BY trx_started;

其中 trx_started 越早的事务越有可能是阻塞源。结合 information_schema.processlist 中的 Time 字段,可以判断一个事务从开始到现在持有了多长时间。不要一看到长事务就立刻 KILL,先通过 trx_query 判断它是在执行大批量写入,还是已经进入空闲但未提交状态。空闲事务在 SHOW PROCESSLIST 中通常表现为 Command 为 Sleep 且 Info 为 NULL,这类事务很多是应用层忘记提交或连接池中的长事务造成,杀掉的风险通常较低,但仍然需要与业务确认后再操作。

MySQL锁表查询InnoDB锁等待元数据锁修改时间:2026-09-23 11:46:15

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/0923/60884.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。