【问题标题】:MariaDB InnoDB table: how to find statement causing "waiting for table metadata lock"MariaDB InnoDB 表:如何查找导致“等待表元数据锁定”的语句
【发布时间】:2017-01-06 00:47:47
【问题描述】:

如何确定 MariaDB 上元数据锁定信息行 (SELECT * FROM information_schema.metadata_lock_info) 中显示的线程 ID 的 SQL 语句是什么?

Server version: 10.0.15-MariaDB MariaDB Server

从 MySQL 的角度来看,所有相关问题都深入到“等待表元数据锁”,但这对 MariaDB 没有帮助,因为它们的自省实现方式与我所知的不同。谷歌搜索并没有出现很多。

“显示完整进程列表”给出如下行:

| 57295 | main  | localhost | joints | Execute |   50 | Waiting for table metadata lock | select ...

它确实显示了语句,但也没有显示它有锁。因此,我按照此处 [0] 的说明打开了元数据锁定信息。这里只提供锁持有者的线程ID,不提供语句:

MariaDB [joints]> SELECT * FROM information_schema.metadata_lock_info;
+-----------+--------------------------+-----------------+----------------------+--------------+----------------+
| THREAD_ID | LOCK_MODE                | LOCK_DURATION   | LOCK_TYPE            | TABLE_SCHEMA | TABLE_NAME     |
+-----------+--------------------------+-----------------+----------------------+--------------+----------------+
|     57322 | MDL_INTENTION_EXCLUSIVE  | MDL_EXPLICIT    | Global read lock     |              |                |
|     57322 | MDL_SHARED_NO_READ_WRITE | MDL_EXPLICIT    | Table metadata lock  | joints       | 16_study       |
|     57322 | MDL_INTENTION_EXCLUSIVE  | MDL_EXPLICIT    | Schema metadata lock | joints       |                |
|     57269 | MDL_SHARED_READ          | MDL_TRANSACTION | Table metadata lock  | joints       | authentication |
|     57301 | MDL_SHARED_READ          | MDL_TRANSACTION | Table metadata lock  | joints       | authentication |
|     57280 | MDL_SHARED_READ          | MDL_TRANSACTION | Table metadata lock  | joints       | authentication |
|     57317 | MDL_SHARED_READ          | MDL_TRANSACTION | Table metadata lock  | joints       | ship           |
|     57271 | MDL_SHARED_READ          | MDL_TRANSACTION | Table metadata lock  | joints       | administration |
|     57264 | MDL_SHARED_READ          | MDL_TRANSACTION | Table metadata lock  | joints       | server         |
+-----------+--------------------------+-----------------+----------------------+--------------+----------------+

我真正想要的是在锁定发生的那一刻看到这两个输出的“连接”。我看不到从这两个“表”中加入数据的方法,因为前者似乎不是表。我想避免得到:

ERROR 1933 (HY000): Target is not running an EXPLAINable command

在尝试实时执行此操作时,由于线程在被检查时结束。

[0]https://mariadb.com/kb/en/mariadb/metadata_lock_info/

【问题讨论】:

  • 是否涉及复制? SHOW FULL PROCESSLIST 没有给出任何线索吗?用户使用autocommit=0吗?
  • 无复制(单服务器)。一般自动提交=1。显示完整进程列表中充满了被锁定的事务,但无助于确定哪个拥有锁定。
  • 要么查找不处于“Lock”状态的项,要么是一个尚未提交的事务,处于SQL之间。寻找最大的“时间”(跳过任何明显的系统线程)。

标签: mariadb


【解决方案1】:

THREAD_ID 映射到information_schema.PROCESSLIST.IDshow [full] processlist; 中的第一列。即:

SELECT * FROM information_schema.METADATA_LOCK_INFO AS mli
JOIN information_schema.PROCESSLIST AS pl ON mli.THREAD_ID = pl.ID

我更喜欢以下内容,以便更容易看到正在发生的事情(尽管换行符不适用于 cli):

SELECT
  mli.THREAD_ID, mli.LOCK_MODE, mli.LOCK_TYPE, 
  CAST(GROUP_CONCAT(DISTINCT CONCAT(mli.TABLE_SCHEMA, '.', mli.TABLE_NAME) ORDER BY mli.TABLE_SCHEMA, mli.TABLE_NAME SEPARATOR '\n') AS CHAR) AS locked_tables, 
  pl.USER, pl.HOST, pl.DB, pl.COMMAND, pl.TIME, pl.STATE, pl.INFO, pl.QUERY_ID, pl.TID
FROM information_schema.METADATA_LOCK_INFO AS mli
JOIN information_schema.PROCESSLIST AS pl ON mli.THREAD_ID = pl.ID
GROUP BY mli.THREAD_ID, mli.LOCK_MODE, mli.LOCK_TYPE
ORDER BY time DESC, pl.ID;

特别有趣的是pl.COMMAND = 'Sleep' 表示某个连接池或其他(主要是只读的)程序正在持有已锁定的打开连接。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-10-29
    • 2011-09-05
    • 2022-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-24
    • 1970-01-01
    相关资源
    最近更新 更多