千金良方:MySQL性能优化金字塔法则
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

9.3 查看是否有MDL锁等待

通过schema_table_lock_waits视图可以查看当前链接线程的MDL锁等待信息,显示哪些会话被MDL锁阻塞,是谁阻塞了这些会话,数据来源:performance_schema下的threads、metadata_locks、events_statements_current表。该视图是MySQL 5.7.9中新增的。

下面是使用schema_table_lock_waits视图查询的结果集。

# 首先需要启用与MDL锁等待事件相关的instruments
mysql> call sys.ps_setup_enable_instrument('wait/lock/metadata/sql/mdl');
+-----------------------+
| summary |
+-----------------------+
| Enabled 1 instruments |
+-----------------------+
1 row in set(0.01 sec)
Query OK, 0 rows affected(0.01 sec)
# 然后 ,使用innodb_lock_waits视图进行查询(注意:请自行模拟一个事务不提交,另一个事务执行DDL操作的场景,即可查询到类似如下的MDL锁等待信息)
mysql> select * from schema_table_lock_waits\G
*************************** 1. row ***************************
              object_schema: xiaoboluo  # 发生MDL锁等待的schema名称
                object_name: test       # 正在等待MDL锁的表名称
          waiting_thread_id: 1217       # 正在等待MDL锁的线程ID
                waiting_pid: 1175       # 正在等待MDL锁的processlist_id
            waiting_account: admin@localhost # 正在等待MDL锁的与线程关联的account名称
          waiting_lock_type: EXCLUSIVE  # 被阻塞的线程正在等待的MDL锁类型
      waiting_lock_duration: TRANSACTION # 该字段来自元数据锁子系统中的锁定时间。有效值为:STATEMENTTRANSACTIONEXPLICIT, STATEMENTTRANSACTION值分别表示在语句或事务结束时会释放的锁。EXPLICIT值表示可以在语句或事务结束时会被保留,需要显式释放的锁,例如:使用FLUSH TABLES WITH READ LOCK获取的全局锁
              waiting_query: alter table test add index i_k(test)# 正在等待 MDL 锁的线程对应的语句文本
          waiting_query_secs: 58 # 正在等待MDL锁的语句已经等待了多长时间(秒)
waiting_query_rows_affected: 0         # 受正在等待 MDL 锁的语句影响的数据行数(该字段来自performance_schema.events_statement_current 表,该表中记录的是语句事件,如果语句是多表联结查询语句,则该语句可能已经执行了一部分 DML 语句,所以即使该语句当前被其他线程阻塞了,被阻塞线程的这个字段也可能出现大于0的值)
waiting_query_rows_examined: 0         # 正在等待 MDL 锁的语句从存储引擎检查的数据行数(同理,该字段来自performance_schema.events_statement_current表)
          blocking_thread_id: 49        # 持有MDL锁的线程ID
                blocking_pid: 7         # 持有MDL锁的processlist ID
            blocking_account: admin@localhost
                                            # 持有MDL锁的与线程关联的account名称
          blocking_lock_type: SHARED_WRITE  #  持有MDL锁的锁类型
      blocking_lock_duration: TRANSACTION   #  waiting_lock_duration 字段的解释相同,只是该值与持有MDL锁的线程相关
    sql_kill_blocking_query: KILL QUERY 7   # 生成的KILL持有MDL锁的查询语句
sql_kill_blocking_connection: KILL 7        # 生成的KILL持有MDL锁的对应会话的语句
*************************** 2. row ***************************
              object_schema: xiaoboluo
                object_name: test
          waiting_thread_id: 1217
                waiting_pid: 1175
            waiting_account: admin@localhost
          waiting_lock_type: EXCLUSIVE
      waiting_lock_duration: TRANSACTION
              waiting_query: alter table test add index i_k(test)
          waiting_query_secs: 58
waiting_query_rows_affected: 0
waiting_query_rows_examined: 0
          blocking_thread_id: 1217
                blocking_pid: 1175
            blocking_account: admin@localhost
          blocking_lock_type: SHARED_UPGRADABLE
      blocking_lock_duration: TRANSACTION
    sql_kill_blocking_query: KILL QUERY 1175
sql_kill_blocking_connection: KILL 1175
2 rows in set(0.00 sec)

下面贴出视图查询语句文本。

SELECT g.object_schema AS object_schema,
      g.object_name AS object_name,
      pt.thread_id AS waiting_thread_id,
      pt.processlist_id AS waiting_pid,
      sys.ps_thread_account(p.owner_thread_id)AS waiting_account,
      p.lock_type AS waiting_lock_type,
      p.lock_duration AS waiting_lock_duration,
      sys.format_statement(pt.processlist_info)AS waiting_query,
      pt.processlist_time AS waiting_query_secs,
      ps.rows_affected AS waiting_query_rows_affected,
      ps.rows_examined AS waiting_query_rows_examined,
      gt.thread_id AS blocking_thread_id,
      gt.processlist_id AS blocking_pid,
      sys.ps_thread_account(g.owner_thread_id)AS blocking_account,
      g.lock_type AS blocking_lock_type,
      g.lock_duration AS blocking_lock_duration,
      CONCAT('KILL QUERY ', gt.processlist_id)AS sql_kill_blocking_query,
      CONCAT('KILL ', gt.processlist_id)AS sql_kill_blocking_connection
  FROM performance_schema.metadata_locks g
INNER JOIN performance_schema.metadata_locks p
    ON g.object_type = p.object_type
  AND g.object_schema = p.object_schema
  AND g.object_name = p.object_name
  AND g.lock_status = 'GRANTED'
  AND p.lock_status = 'PENDING'
INNER JOIN performance_schema.threads gt ON g.owner_thread_id = gt.thread_id
INNER JOIN performance_schema.threads pt ON p.owner_thread_id = pt.thread_id
  LEFT JOIN performance_schema.events_statements_current gs ON g.owner_thread_id =gs.thread_id
  LEFT JOIN performance_schema.events_statements_current ps ON p.owner_thread_id =ps.thread_id
WHERE g.object_type = 'TABLE';