《高性能MySQL》读书笔记 第三章 PerformanceSchema

这章我只记录了一小部分,因为水平有限,我看得较吃力,在使用AI辅助理解与做笔记时出现了一些与原文有争议的地方,我暂时没有能力判断谁是对的,这本书就先看到这了

引言

在高负载下调优数据库性能是一个迭代循环的过程。每次进行更改以调优数据库的性能时,都需要了解更改是否有什么影响。*查询速度比以前快吗?锁是否会减慢应用程序的速度,或者是否已经完全消失了?内存使用情况改变了吗?等待磁盘的时间改变了吗?*一旦理解了如何回答这些问题,你将能够更快地评估和应对日常情况。

Performance Schema 是一个存储回答上述问题所需数据的数据库。本章将帮助你了解 Performance Schema 的工作原理、局限性,以及如何更好地使用它和 sys Schema 来搞清楚 MySQL 内部的运行细节。

Performance Schema介绍

Performance Schema提供了有关MySQL服务器内部运行的操作上的底层指标。在解释其工作机制前,先了解两个概念

  • 程序插桩(instrument)

第一个概念是程序插桩。程序插桩是在 MySQL 代码中插入探测代码,以获取我们想了解的信息。例如,如果想收集关于元数据锁(MDL 锁)的使用情况,需要启用 wait/lock/meta-data/sql/mdl 这个插桩。

简单理解的话,可以将其当做关键位置的监控,如果开启MDL锁的程序插桩,每当MySQL加MDL锁、等待或释放MDL锁时,就会被记录。若关闭,则不会被记录。

  • 消费者表(consumer)

第二个概念是消费者表(consumer),指的是存储关于程序插桩代码信息的表。如果我们为查询模块添加插桩,相应的消费者表将记录诸如执行总数、未使用索引的次数、花费的时间等信息。大多数人都将消费者表与 Performance Schema 紧密联系在一起。

简单理解的话,可以将其当做存放程序插桩数据的记录表,监控(程序插桩)采集到的数据必须存储在某个地方,而这个地方就是Consumer,也就是 Performance Schema 里的各种表。

Consumer 决定:采集到的数据要不要存、存到哪张表、存当前还是历史


两者的关系:必须同时开才有用

Instrument 打开 + Consumer 打开 = Performance Schema 生效

  • 只开 Instrument,不开 Consumer → 数据采集了但不存,等于白采。
  • 只开 Consumer,不开 Instrument → 表是空的,没有数据进来。

这就是为什么 Performance Schema 有两张关键配置表:

  1. setup_instruments(控制探头)
  2. setup_consumers(控制记录表)

启用插桩会调用额外的代码,将会消耗额外的CPU资源。

插桩元件

在performance_schema中,setup_instruments表包含所有支持的插桩的列表。所有插桩的名称都由用斜杆分割的部件组成。比如:

  • statement/sql/select

  • wait/synch/mutex/innodb/autoinc_mutex

插桩名称的最左边部分表示插桩的类型。因此,statement表示插桩类型是statement,wait表示插桩类型是wait,以此类推。

名称字段中的其余部分从左至右依次表示从通用到特定的子系统。继续以前面的例子说明:

  • select是sql子系统的一部分,属于statement类型。

  • autoinc_mutex属于innodb,它是更通用的插桩类mutex的一部分,而mutex又是更通用的插桩类型wait的sync插桩的一部分。

setup_instruments 表

performance_schema的setup_instruments表是MySQL Performance Schema里控制所有插桩(instrument)开关的核心配置表。

可以简单理解为:

  • 每一行代表一个可监控的事件类型(比如 SQL 执行、锁等待、内存分配、网络包接收等)

  • 每一列是这个插桩的属性配置,决定它要不要采集数据、要不要计时、有什么特性

各列的含义:

列名 作用 核心说明
NAME 插桩的唯一名称 / 分层命名,比如 statement/sql/error,一眼就能看出是「SQL 语句类 → SQL 执行 → 错误」相关的监控
ENABLED 插桩是否启用 YES= 开启(采集数据),NO= 关闭(不采集,零开销)
TIMED 是否记录耗时 YES= 采集事件的执行时间(用于统计耗时、慢查询),NULL= 该插桩不支持计时(比如内存类插桩)
PROPERTIES 插桩的属性标签 标注插桩的特性,比如 mutable(可动态修改)、global_statistics(全局统计类)
VOLATILITY 插桩的稳定性 / 开销等级 0 = 稳定、低开销(默认开启);1 = 可能有额外开销 / 不稳定(按需开启)
DOCUMENTATION 插桩的官方说明 用自然语言解释这个插桩到底监控什么,是理解插桩作用的关键

查询示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
mysql> SELECT * FROM performance_schema.setup_instruments
    -> WHERE DOCUMENTATION IS NOT NULL LIMIT 5, 5\G -- 从第6行开始,取5行,\G表示竖着展示结果
*************************** 1. row ***************************
           NAME: statement/sql/error
        ENABLED: YES
          TIMED: YES
     PROPERTIES: 
        VOLATILITY: 0
DOCUMENTATION: Invalid SQL queries (syntax error).
*************************** 2. row ***************************
           NAME: statement/abstract/Query
        ENABLED: YES
          TIMED: YES
     PROPERTIES: mutable
        VOLATILITY: 0
DOCUMENTATION: SQL query just received from the network. At this point, the real statement type is unknown, the type will be refined after SQL parsing.
*************************** 3. row ***************************
           NAME: statement/abstract/new_packet
        ENABLED: YES
          TIMED: YES
     PROPERTIES: mutable
        VOLATILITY: 0
DOCUMENTATION: New packet just received from the network. At this point, the real command type is unknown, the type will be refined after reading the packet header.
*************************** 4. row ***************************
           NAME: statement/abstract/relay_log
        ENABLED: YES
          TIMED: YES
     PROPERTIES: mutable
        VOLATILITY: 0
DOCUMENTATION: New event just read from the relay log. At this point, the real statement type is unknown, the type will be refined after parsing the event.
*************************** 5. row ***************************
           NAME: memory/performance_schema/mutex_instances
        ENABLED: YES
          TIMED: NULL
     PROPERTIES: global_statistics
        VOLATILITY: 1
DOCUMENTATION: Memory used for table performance_schema.mutex_instances
5 rows in set (0.00 sec)

对于许多插桩而言,DOCUMENTATION列可能为空,需要靠自己来理解插桩的作用。

消费者表的组织

消费者表是插桩发送信息的目的地。程序插桩的采集结果存储在Performance Schema数据库的多个表中,在MySQL 8.0.25社区版的performance_schema中包含110个表。基于它们的用途,可分为以下几个类别。

当前和历史数据

存放事件的表名包含如下结尾:

  • *_current 当前服务器上进行中的事件。

  • *_history 每个线程最近完成的 10 个事件。

  • *_history_long 从全局来看,每个线程最近完成的 10000 个事件。

*_history*_history_long 表的大小是可配置的。

总结:

后缀 全称 核心作用 存储范围 可配置性
*_current 当前表 存储正在执行中的事件 仅记录当前服务器上「未完成」的操作,事件执行完成后会从该表移除 不可手动配置大小,由 MySQL 自动维护
*_history 历史表 存储最近完成的短周期事件 每个线程最多保留最近完成的 10 个事件(默认值),新事件会覆盖旧事件 可配置,通过 performance_schema_events_waits_history_size 等参数调整每个线程的保留条数
*_history_long 长历史表 存储长期留存的全量事件 全局维度,每个线程最多保留最近完成的 10000 个事件(默认值),适合做历史分析 可配置,通过 performance_schema_events_waits_history_long_size 等参数调整全局保留条数

比如(以 SQL 语句为例):

events_statements_current:记录当前正在执行的 SQL,比如一个慢查询还没跑完,就能在这个表里看到它的执行进度、耗时等信息。

events_statements_history:每个线程执行完 SQL 后,会把这条 SQL 存入这个表,最多保留 10 条,适合排查「刚执行完的操作」。

events_statements_history_long:全局保留每个线程最近 10000 条执行完的 SQL,适合做历史性能分析,比如统计一天内的慢 SQL 分布。


MySQL 把事件按业务维度分成了 4 大类,每一类对应一套 *_current/*_history/*_history_long 表:

  • events_waits 记录底层服务器等待,例如获取互斥对象。是排查性能瓶颈的核心表。

  • events_statements 记录所有SQL查询语句,是最常用的性能分析表。

  • events_stages 记录SQL执行的内部阶段(SQL执行的每一步过程),例如创建临时表或发送数据。用来拆解 SQL 执行的全流程耗时。

  • events_transactions 记录所有事务的生命周期,是排查事务问题的核心表。

汇总表和摘要

汇总表保存有关该表所建议的内容的聚合信息。例如,memory_summary_by_thread_by_event_name表保存了用户连接或任何后台线程的每个MySQL线程的聚合内存使用情况。

摘要是一种通过删除查询中的变量来聚合查询的方法。例如以下查询:

1
2
3
SELECT user,birthdate FROM users WHERE user_id=19;
SELECT user,birthdate FROM users WHERE user_id=13;
SELECT user,birthdate FROM users WHERE user_id=27;

该查询的摘要是:

1
SELECT user,birthdate FROM users WHERE user_id=?

这允许Performance Schema跟踪摘要的延迟等指标,而无须单独保留查询的每个变体。

实例表(Instance)

Instance(实例)指 MySQL运行时创建的对象实体。例如,file_instances表包含文件名和访问这些文件的线程数。

原文对实例表的描述:实例是指对象实例,用于MySQL安装程序。例如,file_instances表包含文件名和访问这些文件的线程数。


这本书的翻译质量似乎有所争议,我看着也挺吃力,未来有缘再看吧…

本站于2025年3月26日建立
使用 Hugo 构建
主题 StackJimmy 设计