MySQL 中的系统库之performance_schema


MySQL学习系列


performance_schema

1. 什么是 performance_schema
MySQL 的 performance_schema 是运行在较低级别的用于监控 MySQL Server运行过程中的资源消耗、 资源等待等情况的一个功能特性, 它具有以下特点。

  • performance_schema 提供了一种在数据库运行时实时检查 Server 内部执行情况的方法。 performance_schema 数据库中的表使用 performance_schema 存储引擎。 该数据库主要关注数据库运行过程中的性能相关数据。
  • performance_schema 通过监视 Server 的事件来实现监视其内部执行情况,“事件” 就是在 Server 内部活动中所做的任何事情以及对应的时间消耗, 利用这些信息来判断 Server 中的相关资源被消耗在哪里。 一般来说, 事件可以是函数调用、 操作系统的等待、 SQL 语句执行的阶段[如 SQL 语句执行过程中的 parsing(解
    析) 或 sorting(排序) 阶段]或者整个 SQL 语句的集合。 采集事件可以方便地提供 Server 中的相关存储引擎对磁盘文件、 表 I/O、 表锁等资源的同步调用信息。
  • 当前活跃事件、 历史事件和事件摘要相关表中记录的信息, 能提供某个事件的执行次数、 使用时长, 进而可用于分析与某个特定线程、 特定对象(如mutex 或 file) 相关联的活动。
  • performance_schema 存储引擎使用 Server 源代码中的“检测点” 来实现事件数据的收集。 对于 performance_schema 实现机制本身的代码没有相关的单独线程来检测, 这与其他功能(如复制或事件计划程序) 不同。
    收集到的事件数据被存储在 performance_schema 数据库的表中。 对于这些表可以使用 SELECT 语句查询, 也可以使用 SQL 语句更新 performance_schema 数据库中的表记录(比如动态修改 performance_schema 的以“setup_” 开头的配置表, 但要注意, 配置表的更改会立即生效, 这会影响数据收集)
  • performance_schema 的表中数据不会持久化存储在磁盘中, 而是保存在内存中, 一旦服务器重启, 这些数据就会丢失(包括配置表在内的整个performance_schema 下的所有数据) 。

2. performance_schema 使用
通过上面介绍, 相信你对于什么是 performance_schema 这个问题了解得更清晰了。 下面开始介绍 performance_schema 的使用。

检查当前数据库版本是否支持

performance_schema 被视为存储引擎, 如果该引擎可用, 则应该在INFORMATION_SCHEMA.ENGINES 表或 show engines 语句的输出中可以看到它的 Support 字段值为 YES, 如下所示。

mysql> show engines;

MySQL 中的系统库之performance_schema_第1张图片
当我们看到 performance_schema 对应的 Support 字段值为 YES 时, 就表示当前的数据库版本是支持 performance_schema 的。 但确认了数据库实例支持performance_schema 存储引擎就可以使用了吗? NO, 很遗憾,performance_schema 在 MySQL 5.6 及之前的版本中默认没有启用, 在 MySQL 5.7及之后的版本中才修改为默认启用。

启用 performance_schema,如果要显式启用或关闭 performance_schema, 则需要使用参数performance_schema=ON|OFF 来设置, 并在 my.cnf 中进行配置。 注意:该参数为只读参数, 需要在实例启动之前设置才生效

mysqld 启动之后, 通过如下语句查看 performance_schema 启用是否生效(值为 ON 表示 performance_schema 已初始化成功且可以使用了; 值为 OFF 表示在启用 performance_schema 时发生某些错误, 可以查看错误日志进行排查) 。

show variables like 'performance_schema';

MySQL 中的系统库之performance_schema_第2张图片
现在, 可以通过查询 INFORMATION_SCHEMA.TABLES 表中与performance_schema 存储引擎相关的元数据, 或者在 performance_schema 库下使用 show tables 语句来了解其存在哪些表。

使用 show tables 语句来查询有哪些 performance_schema 引擎表。

use performance_schema;
show tables;
mysql> use performance_schema;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+------------------------------------------------------+
| Tables_in_performance_schema                         |
+------------------------------------------------------+
| accounts                                             |
| cond_instances                                       |
| events_stages_current                                |
| events_stages_history                                |
| events_stages_history_long                           |
| events_stages_summary_by_account_by_event_name       |
| events_stages_summary_by_host_by_event_name          |
| events_stages_summary_by_thread_by_event_name        |
| events_stages_summary_by_user_by_event_name          |
| events_stages_summary_global_by_event_name           |
| events_statements_current                            |
| events_statements_history                            |
| events_statements_history_long                       |
| events_statements_summary_by_account_by_event_name   |
| events_statements_summary_by_digest                  |
| events_statements_summary_by_host_by_event_name      |
| events_statements_summary_by_program                 |
| events_statements_summary_by_thread_by_event_name    |
| events_statements_summary_by_user_by_event_name      |
| events_statements_summary_global_by_event_name       |
| events_transactions_current                          |
| events_transactions_history                          |
| events_transactions_history_long                     |
| events_transactions_summary_by_account_by_event_name |
| events_transactions_summary_by_host_by_event_name    |
| events_transactions_summary_by_thread_by_event_name  |
| events_transactions_summary_by_user_by_event_name    |
| events_transactions_summary_global_by_event_name     |
| events_waits_current                                 |
| events_waits_history                                 |
| events_waits_history_long                            |
| events_waits_summary_by_account_by_event_name        |
| events_waits_summary_by_host_by_event_name           |
| events_waits_summary_by_instance                     |
| events_waits_summary_by_thread_by_event_name         |
| events_waits_summary_by_user_by_event_name           |
| events_waits_summary_global_by_event_name            |
| file_instances                                       |
| file_summary_by_event_name                           |
| file_summary_by_instance                             |
| global_status                                        |
| global_variables                                     |
| host_cache                                           |
| hosts                                                |
| memory_summary_by_account_by_event_name              |
| memory_summary_by_host_by_event_name                 |
| memory_summary_by_thread_by_event_name               |
| memory_summary_by_user_by_event_name                 |
| memory_summary_global_by_event_name                  |
| metadata_locks                                       |
| mutex_instances                                      |
| objects_summary_global_by_type                       |
| performance_timers                                   |
| prepared_statements_instances                        |
| replication_applier_configuration                    |
| replication_applier_status                           |
| replication_applier_status_by_coordinator            |
| replication_applier_status_by_worker                 |
| replication_connection_configuration                 |
| replication_connection_status                        |
| replication_group_member_stats                       |
| replication_group_members                            |
| rwlock_instances                                     |
| session_account_connect_attrs                        |
| session_connect_attrs                                |
| session_status                                       |
| session_variables                                    |
| setup_actors                                         |
| setup_consumers                                      |
| setup_instruments                                    |
| setup_objects                                        |
| setup_timers                                         |
| socket_instances                                     |
| socket_summary_by_event_name                         |
| socket_summary_by_instance                           |
| status_by_account                                    |
| status_by_host                                       |
| status_by_thread                                     |
| status_by_user                                       |
| table_handles                                        |
| table_io_waits_summary_by_index_usage                |
| table_io_waits_summary_by_table                      |
| table_lock_waits_summary_by_table                    |
| threads                                              |
| user_variables_by_thread                             |
| users                                                |
| variables_by_thread                                  |
+------------------------------------------------------+
87 rows in set (0.00 sec)

mysql>

现在, 我们知道了在当前版本中, performance_schema 库下一共有 87 个表,那么这些表都用于存放什么数据呢? 我们如何使用它们来查询数据呢? 先来看看这些表是如何分类的。

3. performance_schema 表的分类
performance_schema 库下的表可以按照监视的不同维度进行分组, 例如:按照不同的数据库对象进行分组、 按照不同的事件类型进行分组, 或者按照事件类型分组之后, 再进一步按照账号、 主机、 程序、 线程、 用户等进行细分。

下面介绍按照事件类型分组记录性能事件数据的表

  • 语句事件记录表: 记录语句事件信息的表, 包括:events_statements_current(当前语句事件表) 、 events_statements_history(历史语句事件表) 、 events_statements_history_long(长语句历史事件表) 以及一些 summary 表(聚合后的摘要表) 。 其中, summary 表还可以根据账号(account)、主机(host) 、 程序(program) 、 线程(thread) 、 用户(user) 和全局(global)再进行细分。
show tables like 'events_statement%';

MySQL 中的系统库之performance_schema_第3张图片

  • 等待事件记录表: 与语句事件记录表类似。
show tables like 'events_wait%';

MySQL 中的系统库之performance_schema_第4张图片

  • 阶段事件记录表: 记录语句执行阶段事件的表, 与语句事件记录表类似。
show tables like 'events_stage%';

MySQL 中的系统库之performance_schema_第5张图片

  • 事务事件记录表: 记录与事务相关的事件的表, 与语句事件记录表类似。
show tables like 'events_transaction%';
  • 监视文件系统层调用的表:
show tables like '%file%';
  • 监视内存使用的表:
show tables like '%memory%';
  • 动态对 performance_schema 进行配置的配置表:
show tables like '%setup%';

现在, 我们已经大概知道了 performance_schema 中主要表的分类, 但如何使用这些表来提供性能事件数据呢?

4. performance_schema 简单配置与使用

当数据库初始化完成并启动时, 并非所有的 instruments( 在采集配置项的配置表中, 每一项都有一个开关字段, 或为 YES, 或为 NO) 和 consumers( 与采集配置项类似, 也有一个对应的事件类型保存表配置项, 为 YES 表示对应的表保存性能数据, 为 NO 表示对应的表不保存性能数据) 都启用了, 所以默认不会收集所有的事件。

可能你想检测的事件并没有打开, 需要进行设置。 可以使用如下两条语句打开对应的 instruments 和 consumers, 我们以配置监测等待事件数据为例进行说明。打开等待事件的采集器配置项开关, 需要修改 setup_instruments 配置表中对应的采集器配置项。

update setup_instruments set enabled='yes',timed='yes' where name like 'wait%';

在这里插入图片描述
打开等待事件的保存表配置项开关, 修改 setup_consumers 配置表中对应的配置项。

update setup_consumers set enabled='yes' where name like 'wait%';

在这里插入图片描述
配置好之后, 我们就可以查看 Server 当前正在做什么了。 可以通过查询events_waits_current 表来得知, 该表中每个线程只包含一行数据, 用于显示每个线程的最新监视事件(正在做的事情)。

mysql> select * from events_waits_current;

在这里插入图片描述
*_current 表中每个线程只保留一条记录, 且一旦线程完成工作, 该表中就不会再记录该线程的事件信息了。 *_history 表中记录每个线程已经执行完成的事件信息, 但每个线程的事件信息只记录 10 条, 再多就会被覆盖掉。 *_history_long表中记录所有线程的事件信息, 但总记录数量是 10000 行, 超过会被覆盖掉。summary 表提供所有事件的汇总信息。 该组中的表以不同的方式汇总事件数据(如: 按用户、 按主机、 按线程等汇总)。

查看最近执行失败的 SQL 语句
使用代码对数据库的某些操作(比如: 使用 Java 的 ORM 框架操作数据库)报出语法错误, 但是代码并没有记录 SQL 语句文本的功能, 在 MySQL 数据库层能否查看到具体的 SQL 语句文本, 看看是否哪里写错了? 这个时候, 大多数人首先想到的就是去查看错误日志。 很遗憾, 对于 SQL 语句的语法错误, 错误日志并不会记录。

实际上, 在 performance_schema 的语句事件记录表中针对每一条语句的执行状态都记录了较为详细的信息, 例如: events_statements_表和events_statements_summary_by_digest 表(events_statements_表记录了语句所有的执行错误信息, 而 events_statements_summary_by_digest 表只记录了语句在执行过程中发生错误的语句记录统计信息, 不记录具体的错误类型, 例如: 不记录语法错误类的信息)。 下面看看如何使用这两个表查询语句发生错误的语句信息。

首先, 我们模拟一条语法错误的 SQL 语句, 使用events_statements_history_long 表或者 events_statements_history 表查询发生语法错误的 SQL 语句:

select * from events_statements_history where mysql_errno=1064\G
mysql> select * from;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
mysql> select * from events_statements_history where mysql_errno=1064\G
*************************** 1. row ***************************
              THREAD_ID: 40
               EVENT_ID: 103
           END_EVENT_ID: 103
             EVENT_NAME: statement/sql/error
                 SOURCE:
            TIMER_START: 37302918840295000
              TIMER_END: 37302919128294000
             TIMER_WAIT: 287999000
              LOCK_TIME: 0
               SQL_TEXT: select * from
                 DIGEST: NULL
            DIGEST_TEXT: NULL
         CURRENT_SCHEMA: performance_schema
            OBJECT_TYPE: NULL
          OBJECT_SCHEMA: NULL
            OBJECT_NAME: NULL
  OBJECT_INSTANCE_BEGIN: NULL
            MYSQL_ERRNO: 1064
      RETURNED_SQLSTATE: 42000
           MESSAGE_TEXT: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use
                 ERRORS: 1
               WARNINGS: 0
          ROWS_AFFECTED: 0
              ROWS_SENT: 0
          ROWS_EXAMINED: 0
CREATED_TMP_DISK_TABLES: 0
     CREATED_TMP_TABLES: 0
       SELECT_FULL_JOIN: 0
 SELECT_FULL_RANGE_JOIN: 0
           SELECT_RANGE: 0
     SELECT_RANGE_CHECK: 0
            SELECT_SCAN: 0
      SORT_MERGE_PASSES: 0
             SORT_RANGE: 0
              SORT_ROWS: 0
              SORT_SCAN: 0
          NO_INDEX_USED: 0
     NO_GOOD_INDEX_USED: 0
       NESTING_EVENT_ID: NULL
     NESTING_EVENT_TYPE: NULL
    NESTING_EVENT_LEVEL: 0
1 row in set (0.00 sec)

不知道错误号是多少, 可以查询发生错误次数不为 0 的语句记录, 在里边找到 SQL_TEXT 和 MESSAGE_TEXT 字段(提示信息为语法错误的就是它)

查看最近的事务执行信息
我们可以通过慢查询日志查询到一条语句的执行总时长, 但是如果数据库中存在着一些大事务在执行过程中回滚了, 或者在执行过程中异常中止, 这个时候慢查询日志就爱莫能助了, 这时我们可以借助 performance_schema 的events_transactions_*表来查看与事务相关的记录, 在这些表中详细记录了是否有事务被回滚、 活跃(长时间未提交的事务也属于活跃事务) 或已提交等信息。

首先需要进行配置启用, 事务事件默认并未启用

update setup_instruments set enabled='yes',timed='yes' where name like 'transaction%';
update setup_consumers set enabled='yes' where name like '%transaction%';

MySQL 中的系统库之performance_schema_第6张图片
开启一个新会话(会话 2) 用于执行事务, 并模拟事务回滚。
在这里插入图片描述
查询活跃事务, 活跃事务表示当前正在执行的事务事件, 需要从events_transactions_current 表中查询。

SELECT * FROM performance_schema.events_transactions_current 
mysql> SELECT * FROM events_transactions_current\G
*************************** 1. row ***************************
                      THREAD_ID: 40
                       EVENT_ID: 119
                   END_EVENT_ID: NULL
                     EVENT_NAME: transaction
                          STATE: ACTIVE
                         TRX_ID: NULL
                           GTID: AUTOMATIC
                  XID_FORMAT_ID: NULL
                      XID_GTRID: NULL
                      XID_BQUAL: NULL
                       XA_STATE: NULL
                         SOURCE:
                    TIMER_START: 37702351140472000
                      TIMER_END: 37990687037226000
                     TIMER_WAIT: 288335896754000
                    ACCESS_MODE: READ WRITE
                ISOLATION_LEVEL: REPEATABLE READ
                     AUTOCOMMIT: NO
           NUMBER_OF_SAVEPOINTS: 0
NUMBER_OF_ROLLBACK_TO_SAVEPOINT: 0
    NUMBER_OF_RELEASE_SAVEPOINT: 0
          OBJECT_INSTANCE_BEGIN: NULL
               NESTING_EVENT_ID: 118
             NESTING_EVENT_TYPE: STATEMENT

会话 2 中回滚事务:
在这里插入图片描述
查询事务事件当前表和事务事件历史记录表, 可以看到在两表中都记录了一行事务事件信息, 线程ID为40的线程执行了一个事务, 事务状态为ROLLED BACK。


mysql> SELECT * FROM events_transactions_current\G
*************************** 1. row ***************************
                      THREAD_ID: 40
                       EVENT_ID: 119
                   END_EVENT_ID: 121
                     EVENT_NAME: transaction
                          STATE: ROLLED BACK
                         TRX_ID: NULL
                           GTID: AUTOMATIC
                  XID_FORMAT_ID: NULL
                      XID_GTRID: NULL
                      XID_BQUAL: NULL
                       XA_STATE: NULL
                         SOURCE:
                    TIMER_START: 37702351140472000
                      TIMER_END: 38061121151922000
                     TIMER_WAIT: 358770011450000
                    ACCESS_MODE: READ WRITE
                ISOLATION_LEVEL: REPEATABLE READ
                     AUTOCOMMIT: NO
           NUMBER_OF_SAVEPOINTS: 0
NUMBER_OF_ROLLBACK_TO_SAVEPOINT: 0
    NUMBER_OF_RELEASE_SAVEPOINT: 0
          OBJECT_INSTANCE_BEGIN: NULL
               NESTING_EVENT_ID: 118
             NESTING_EVENT_TYPE: STATEMENT

但是当我们关闭会话 2 以后, 事务事件当前表中的记录就消失了。

你可能感兴趣的:(sql,mysql,mysql,数据库,sql)