MySQL 中的 performance_schema 常用诊断表

performance_schema 是 MySQL 5.5 引入的一个较为特殊的数据库,它主要用于监控 MySQL 服务器的性能。与 information_schema 不同,performance_schema 提供的是底层运行时数据,包括等待事件、锁、语句执行阶段、内存分配等细节信息。对于 DBA 和开发人员来说,它是一把性能诊断的“手术刀”。在面试中,关于 performance_schema 的常见问题往往集中在:它有哪些核心表、如何定位慢查询、如何分析锁等待、如何查看线程状态等。本文将从实战角度出发,梳理最常用的诊断表及其典型用法。

一、performance_schema 的基本概念

在深入表之前,需要理解几个基本概念:

  • Instrument(生产者):采集点,例如一个 mutex 等待、一个 SQL 语句的执行阶段。
  • Consumer(消费者):存储采集数据的表,例如 events_statements_current
  • Thread(线程):每个连接对应一个线程,performance_schema 中的很多表都围绕线程 ID 组织。
  • Setup 表:用于动态开启或关闭某些 instrument 和 consumer,例如 setup_instrumentssetup_consumers

默认情况下,performance_schema 是开启的(MySQL 5.6.6 以后),但部分 consumer 可能未启用。诊断前建议先确认:

SHOW VARIABLES LIKE 'performance_schema';
SELECT * FROM performance_schema.setup_consumers;

二、按诊断场景分类的常用表

1. 语句级诊断:定位慢 SQL 与执行细节

events_statements_current
当前每个线程正在执行的语句。字段包括 THREAD_IDEVENT_IDSQL_TEXTTIMER_WAIT(执行耗时,单位皮秒)、LOCK_TIMEROWS_EXAMINED 等。常用于实时查看某个连接卡在什么 SQL 上。

events_statements_history
每个线程最近执行的 N 条语句(默认 10 条)。适合事后分析,比如某个连接刚刚执行过什么。

events_statements_history_long
全局最近执行的 10000 条语句(可配置)。用于全局慢查询回溯,但注意它会消耗较多内存。

events_statements_summary_by_digest
这是最常用的聚合表之一。它按 SQL 的 digest(归一化后的指纹)分组,统计总执行次数、总耗时、平均耗时、扫描行数等。面试常问:“如何找出执行次数最多或总耗时最大的 SQL?”答案就是查这张表:

SELECT DIGEST_TEXT, COUNT_STAR, SUM_TIMER_WAIT/1e12 AS total_sec,
       AVG_TIMER_WAIT/1e12 AS avg_sec, SUM_ROWS_EXAMINED
FROM performance_schema.events_statements_summary_by_digest
ORDER BY SUM_TIMER_WAIT DESC LIMIT 10;

2. 等待事件诊断:分析瓶颈在哪儿

events_waits_current
当前线程正在等待的事件。例如等待表锁、行锁、IO、mutex 等。字段 EVENT_NAME 表示等待类型,TIMER_WAIT 表示已等待时间。

events_waits_history / events_waits_history_long
历史等待事件,用于分析过去一段时间内哪些等待最耗时。

events_waits_summary_global_by_event_name
按等待事件名称聚合。可以快速看出系统整体上时间花在了哪类等待上:

SELECT EVENT_NAME, COUNT_STAR, SUM_TIMER_WAIT/1e12 AS total_sec
FROM performance_schema.events_waits_summary_global_by_event_name
ORDER BY SUM_TIMER_WAIT DESC LIMIT 10;

如果 wait/io/table/sql/handlerwait/io/file/innodb/innodb_data_file 排在前列,说明 IO 是瓶颈。

3. 锁与事务诊断:排查阻塞和死锁

data_locks(MySQL 8.0,之前是 innodb_locks
当前持有的锁信息,包括锁类型、锁模式、锁定的表与索引、事务 ID。

data_lock_waits(之前是 innodb_lock_waits
显示锁等待关系:哪个事务在等哪个事务持有的锁。结合 data_locksinformation_schema.INNODB_TRX 可以完整还原阻塞链。

events_transactions_current
当前每个线程的事务状态,包括事务隔离级别、是否只读、开始时间等。

events_transactions_history_long
历史事务记录,可用于分析长事务。

面试题:“如何找出谁阻塞了谁?”典型查询:

SELECT 
  r.trx_id AS waiting_trx,
  r.trx_mysql_thread_id AS waiting_thread,
  b.trx_id AS blocking_trx,
  b.trx_mysql_thread_id AS blocking_thread
FROM performance_schema.data_lock_waits w
JOIN information_schema.INNODB_TRX b ON b.trx_id = w.BLOCKING_ENGINE_TRANSACTION_ID
JOIN information_schema.INNODB_TRX r ON r.trx_id = w.REQUESTING_ENGINE_TRANSACTION_ID;

4. 线程与连接诊断

threads
所有线程的信息,包括线程 ID、名称、类型(FOREGROUND/BACKGROUND)、进程 ID 等。与 PROCESSLIST 相比,它提供更底层的线程数据。

events_connections_current / history
连接事件,可以查看每个连接的建立时间、状态变化。

session_connect_attrs
连接属性,例如客户端程序名、版本、操作系统等。用于识别连接来源。

5. 内存与 IO 诊断

memory_summary_by_thread_by_event_name
按线程和内存事件统计内存分配。可以定位哪个线程占用了大量内存。

file_summary_by_instance
按文件实例统计 IO 次数、读写字节数、延迟等。用于分析热点文件。

table_io_waits_summary_by_table
按表统计 IO 等待。可以找出 IO 最重的表。

三、实战组合:一个完整的诊断流程

假设线上反馈数据库变慢,可以按以下步骤排查:

  1. 看当前正在执行什么

    SELECT THREAD_ID, SQL_TEXT, TIMER_WAIT/1e12 AS sec
    FROM performance_schema.events_statements_current
    WHERE SQL_TEXT IS NOT NULL;
    
  2. 看历史最耗时的 SQL 指纹

    SELECT DIGEST_TEXT, SUM_TIMER_WAIT/1e12 AS total_sec
    FROM performance_schema.events_statements_summary_by_digest
    ORDER BY SUM_TIMER_WAIT DESC LIMIT 5;
    
  3. 看等待瓶颈

    SELECT EVENT_NAME, SUM_TIMER_WAIT/1e12 AS total_sec
    FROM performance_schema.events_waits_summary_global_by_event_name
    ORDER BY SUM_TIMER_WAIT DESC LIMIT 5;
    
  4. 看锁等待

    SELECT * FROM performance_schema.data_lock_waits;
    
  5. 看长事务

    SELECT trx_id, trx_state, trx_started, trx_mysql_thread_id
    FROM information_schema.INNODB_TRX
    ORDER BY trx_started;
    

四、面试常见问题与回答要点

  • 问:performance_schema 和 slow query log 有什么区别?
    答:slow query log 是事后记录,粒度粗、有 IO 开销;performance_schema 是内存中的实时统计,粒度细,可动态开启,但重启后丢失。

  • 问:如何找出全表扫描的 SQL?
    答:查 events_statements_summary_by_digest,关注 SUM_NO_INDEX_USEDSUM_NO_GOOD_INDEX_USED 大于 0 的记录。

  • 问:performance_schema 对性能有影响吗?
    答:有,但可控。可以通过 setup_instrumentssetup_consumers 只开启需要的采集项。默认配置下开销通常小于 5%。

  • 问:如何查看某个线程的历史 SQL?
    答:用 events_statements_history,按 THREAD_ID 过滤。

五、总结

performance_schema 是 MySQL 性能诊断的核心工具。掌握以下几张表基本可以应对大多数面试和实战场景:

  • 语句:events_statements_summary_by_digestevents_statements_current
  • 等待:events_waits_summary_global_by_event_name
  • 锁:data_locksdata_lock_waits
  • 事务:events_transactions_current
  • 线程:threads
  • 内存/IO:memory_summary_by_thread_by_event_nametable_io_waits_summary_by_table

建议在测试环境多练习这些查询,理解每个字段的含义,面试时才能对答如流。

未经允许不得转载:任鹏个人博客 » MySQL 中的 performance_schema 常用诊断表

赞 (0) 打赏

评论 0

取消
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏