MySQL高阶讲座之：`MySQL`的`Wait Events`：如何通过`Performance Schema`分析瓶颈。

admin
Wed, 20 Aug 2025 11:14:18 +0000
Mysql, events, mysql, wait

各位观众老爷，大家好！我是你们的老朋友，今天咱们聊点MySQL里稍微深奥但又非常实用的话题：Wait Events，以及如何用Performance Schema这把瑞士军刀来分析性能瓶颈。准备好了吗？系好安全带，我们要开车了！ 开篇：什么是Wait Events？ 为什么要关心它？ 想象一下，你在一家餐厅等餐，这“等待”就是一种Wait Event。在MySQL的世界里，线程执行SQL语句的时候，也经常需要等待，比如等待磁盘I/O、等待锁、等待网络数据等等。这些等待，就是Wait Events。 为什么我们要关心Wait Events？ 因为性能瓶颈往往就藏在这些等待里！ 如果你的MySQL服务器CPU利用率不高，但响应速度却很慢，那很有可能就是线程在等待某些资源。找到这些等待，就能精准定位性能瓶颈，对症下药。 Performance Schema：你的MySQL侦察兵 Performance Schema是MySQL自带的性能监控工具，它就像一位默默无闻的侦察兵，记录着MySQL服务器内部各种事件的发生情况，包括Wait Events。 开启Performance Schema后， …

继续阅读“MySQL高阶讲座之：`MySQL`的`Wait Events`：如何通过`Performance Schema`分析瓶颈。”

The post MySQL高阶讲座之：`MySQL`的`Wait Events`：如何通过`Performance Schema`分析瓶颈。 first appeared on 智猿学院-前后端，数据库，人工智能，云计算等领域前沿技术讲座.

各位观众老爷，大家好！我是你们的老朋友，今天咱们聊点MySQL里稍微深奥但又非常实用的话题：Wait Events，以及如何用Performance Schema这把瑞士军刀来分析性能瓶颈。准备好了吗？系好安全带，我们要开车了！

开篇：什么是Wait Events？ 为什么要关心它？

想象一下，你在一家餐厅等餐，这“等待”就是一种Wait Event。在MySQL的世界里，线程执行SQL语句的时候，也经常需要等待，比如等待磁盘I/O、等待锁、等待网络数据等等。这些等待，就是Wait Events。

为什么我们要关心Wait Events？ 因为性能瓶颈往往就藏在这些等待里！ 如果你的MySQL服务器CPU利用率不高，但响应速度却很慢，那很有可能就是线程在等待某些资源。找到这些等待，就能精准定位性能瓶颈，对症下药。

Performance Schema：你的MySQL侦察兵

Performance Schema是MySQL自带的性能监控工具，它就像一位默默无闻的侦察兵，记录着MySQL服务器内部各种事件的发生情况，包括Wait Events。 开启Performance Schema后，你可以通过查询相关表来获取详细的等待信息。

如何开启Performance Schema？

Performance Schema默认是开启的，但为了确保万无一失，你可以检查一下：

SELECT NAME, ENABLED FROM performance_schema.setup_instruments WHERE NAME LIKE '%wait%';

如果ENABLED是NO，那就要开启它了：

UPDATE performance_schema.setup_instruments SET ENABLED = 'YES' WHERE NAME LIKE '%wait%';
UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME LIKE '%wait%';

修改后，需要重启MySQL服务才能生效。 注意：开启Performance Schema会对MySQL服务器产生一定的性能影响，特别是当监控的事件非常多的时候。 所以，在生产环境中要谨慎评估，根据实际需求开启必要的监控。

Performance Schema中的关键表：Wait Events的藏宝图

Performance Schema里有很多表，但对于分析Wait Events来说，下面几个表是最重要的：

events_waits_current: 当前正在等待的事件。

events_waits_history: 最近发生的等待事件的历史记录（每个线程）。

events_waits_history_long: 较长时间内的等待事件的历史记录（所有线程）。

wait_classes_global_by_event_name: 按事件名称统计的全局等待信息。

这些表就像藏宝图一样，指引我们找到性能瓶颈所在。

实战演练：利用Performance Schema分析常见瓶颈

下面，我们通过几个例子，来看看如何利用Performance Schema分析常见的性能瓶颈。

1. 磁盘I/O瓶颈

如果你的MySQL服务器经常出现磁盘I/O瓶颈，可以尝试以下步骤来分析：

查看当前正在等待磁盘I/O的线程：

SELECT
    thread_id,
    event_name,
    object_name,
    index_name,
    operation,
    number_of_bytes
FROM
    performance_schema.events_waits_current
WHERE
    event_name LIKE 'wait/io/file/%'
ORDER BY
    number_of_bytes DESC
LIMIT 10;

这个查询会列出当前正在等待磁盘I/O的线程ID、事件名称、对象名称（表名）、索引名称、操作类型（读/写）以及等待的字节数。

查看历史磁盘I/O等待事件：

SELECT
    event_name,
    COUNT(*) AS count,
    SUM(timer_wait) AS total_latency,
    AVG(timer_wait) AS avg_latency
FROM
    performance_schema.events_waits_history_long
WHERE
    event_name LIKE 'wait/io/file/%'
GROUP BY
    event_name
ORDER BY
    total_latency DESC
LIMIT 10;

这个查询会列出历史磁盘I/O等待事件的名称、数量、总延迟时间以及平均延迟时间。

分析结果：

如果wait/io/file/innodb/innodb_data_file或wait/io/file/myisam/myisam_data事件的total_latency很高，说明InnoDB或MyISAM的数据文件I/O是瓶颈。

如果wait/io/file/innodb/innodb_log_file事件的total_latency很高，说明InnoDB的日志文件I/O是瓶颈。

如果wait/io/file/sql/format事件的total_latency很高，说明慢查询日志的写入是瓶颈。

解决方案：

优化SQL语句： 减少不必要的磁盘I/O。

优化索引： 确保查询能够有效地利用索引。

升级硬件： 使用更快的磁盘（SSD）。

调整InnoDB参数： 例如，增加innodb_buffer_pool_size可以减少磁盘I/O。

调整操作系统参数： 优化文件系统的性能。

2. 锁等待瓶颈

锁是MySQL中保证数据一致性的重要机制，但过多的锁等待会导致性能下降。

查看当前正在等待锁的线程：

SELECT
    thread_id,
    event_name,
    object_name,
    object_instance_begin
FROM
    performance_schema.events_waits_current
WHERE
    event_name LIKE 'wait/lock/table/%' OR event_name LIKE 'wait/lock/metadata/%'
ORDER BY
    timer_wait DESC
LIMIT 10;

这个查询会列出当前正在等待表锁或元数据锁的线程ID、事件名称、对象名称（表名）以及锁的实例地址。

查看历史锁等待事件：

SELECT
    event_name,
    COUNT(*) AS count,
    SUM(timer_wait) AS total_latency,
    AVG(timer_wait) AS avg_latency
FROM
    performance_schema.events_waits_history_long
WHERE
    event_name LIKE 'wait/lock/table/%' OR event_name LIKE 'wait/lock/metadata/%'
GROUP BY
    event_name
ORDER BY
    total_latency DESC
LIMIT 10;

这个查询会列出历史锁等待事件的名称、数量、总延迟时间以及平均延迟时间。

分析结果：

如果wait/lock/table/sql/handler事件的total_latency很高，说明表锁等待是瓶颈。

如果wait/lock/metadata/sql/mdl事件的total_latency很高，说明元数据锁等待是瓶颈。

解决方案：

优化SQL语句： 减少事务的持有时间，避免长时间锁定资源。

调整事务隔离级别： 考虑使用较低的事务隔离级别，以减少锁的竞争。 但要注意可能带来的数据一致性问题。

优化索引： 确保查询能够有效地利用索引，避免全表扫描，从而减少锁的范围。

分解大事务： 将大事务分解成多个小事务，减少锁的持有时间。

使用乐观锁： 在某些场景下，可以使用乐观锁来避免显式锁的使用。

3. 网络I/O瓶颈

如果MySQL服务器与客户端之间的网络连接存在瓶颈，也会导致性能下降。

查看当前正在等待网络I/O的线程：

SELECT
    thread_id,
    event_name
FROM
    performance_schema.events_waits_current
WHERE
    event_name LIKE 'wait/io/socket/%'
ORDER BY
    timer_wait DESC
LIMIT 10;

这个查询会列出当前正在等待网络I/O的线程ID和事件名称。

查看历史网络I/O等待事件：

SELECT
    event_name,
    COUNT(*) AS count,
    SUM(timer_wait) AS total_latency,
    AVG(timer_wait) AS avg_latency
FROM
    performance_schema.events_waits_history_long
WHERE
    event_name LIKE 'wait/io/socket/%'
GROUP BY
    event_name
ORDER BY
    total_latency DESC
LIMIT 10;

这个查询会列出历史网络I/O等待事件的名称、数量、总延迟时间以及平均延迟时间。

分析结果：

如果wait/io/socket/sql/server_unix_socket事件的total_latency很高，说明Unix套接字连接存在瓶颈（通常发生在MySQL服务器和客户端在同一台机器上）。

如果wait/io/socket/sql/server_tcp_socket事件的total_latency很高，说明TCP套接字连接存在瓶颈（通常发生在MySQL服务器和客户端不在同一台机器上）。

解决方案：

优化网络环境： 确保MySQL服务器和客户端之间的网络连接稳定、带宽充足。

减少网络传输的数据量： 优化SQL语句，只返回必要的数据。

使用连接池： 减少频繁创建和销毁连接的开销。

启用压缩： 可以使用MySQL的压缩协议来减少网络传输的数据量。

4. CPU竞争瓶颈

即使CPU利用率不高，线程也可能因为竞争而等待。

查看等待CPU的线程:

SELECT
    thread_id,
    event_name,
    COUNT(*) AS count,
    SUM(timer_wait) AS total_latency
FROM performance_schema.events_waits_summary_global_by_event_name
WHERE event_name LIKE 'wait/synch/mutex/sql/TC_LOG_MMAP::mutex'
GROUP BY thread_id, event_name
ORDER BY total_latency DESC
LIMIT 10;

SELECT * FROM performance_schema.threads WHERE INSTR(processlist_info, "TC_LOG_MMAP::mutex") > 0;

分析结果：

高延迟的wait/synch/mutex/sql/TC_LOG_MMAP::mutex表示线程等待访问TC_LOG_MMAP互斥锁，这通常与二进制日志写入有关。

解决方案：

优化二进制日志写入： 减少二进制日志写入量，例如，通过减少不必要的DML操作。

调整sync_binlog参数： 调整sync_binlog参数的值。 如果sync_binlog=0，则MySQL不会强制将二进制日志同步到磁盘，这可以提高性能，但可能会导致数据丢失。

升级硬件： 更快的磁盘可以减少二进制日志写入的延迟。

更高级的技巧：结合其他Performance Schema表进行分析

除了上面介绍的几个表之外，Performance Schema还有很多其他的表，可以提供更丰富的信息。 例如，你可以将events_waits_current表与threads表关联起来，查看正在等待的线程的详细信息，如连接的客户端IP地址、执行的SQL语句等。

SELECT
    t.thread_id,
    t.name,
    t.processlist_user,
    t.processlist_host,
    t.processlist_db,
    t.processlist_command,
    t.processlist_time,
    t.processlist_state,
    t.processlist_info,
    ewc.event_name
FROM
    performance_schema.threads t
        INNER JOIN
    performance_schema.events_waits_current ewc ON t.thread_id = ewc.thread_id
WHERE
    ewc.event_name LIKE 'wait/lock/table/sql/handler'
ORDER BY ewc.timer_wait DESC
LIMIT 10;

这个查询会列出正在等待表锁的线程的详细信息，包括线程ID、名称、用户、主机、数据库、命令、时间、状态、执行的SQL语句以及等待的事件名称。

总结：Wait Events + Performance Schema = 性能调优利器

今天，我们一起学习了MySQL的Wait Events以及如何利用Performance Schema来分析性能瓶颈。 掌握这些知识，你就能像一位经验丰富的医生一样，快速诊断MySQL服务器的“病情”，并开出“药方”。

记住，性能调优是一个持续的过程，需要不断地监控、分析和优化。 Performance Schema只是一个工具，关键在于你如何使用它。 希望今天的讲座能够帮助你更好地理解MySQL的内部机制，提升你的性能调优能力。

友情提示：

在生产环境中，要谨慎开启Performance Schema，并根据实际需求配置监控的事件。

定期分析Performance Schema的数据，及时发现潜在的性能问题。

结合其他的监控工具，如慢查询日志、系统监控工具等，可以更全面地了解MySQL服务器的运行状况。

实践是检验真理的唯一标准，多动手尝试，才能真正掌握这些知识。

好了，今天的讲座就到这里。 感谢大家的收看，我们下次再见！ 祝大家工作顺利，bug少少！