Mysql 事件记录 | performance_schema全方位介绍

时间:2022-05-02 01:38:52

Mysql 事件记录 | performance_schema全方位介绍

| 导语

在上一篇 初相识|performance_schema全方位介绍 中,我们详细介绍了performance_schema的配置表,坚持读完的是真爱,也恭喜大家翻过了一座火焰山。相信有不少人读完之后,已经迫不及待的想要跃跃欲试了,今天将带领大家一起踏上系列第三篇的征程(全系共7个篇章),在这一期里,我们将为大家全面讲解performance_schema中事件原始记录表。下面,请跟随我们一起开始performance_schema系统的学习之旅吧。

| 等待事件表

通常,我们在碰到性能瓶颈时,如果其他的方法难以找出性能瓶颈的时候(例如:硬件负载不高、SQL优化和库表结构优化都难以奏效的时候),我们常常需要借助于等待事件来进行分析,找出在MySQL Server内部,到底数据库响应慢是慢在哪里。

等待事件记录表包含三张表,这些表记录了当前与最近在MySQL实例中发生了哪些等待事件,时间消耗是多少。

  • events_waits_current表:记录当前正在执行的等待事件的,每个线程只记录1行记录
  • events_waits_history表:记录已经执行完的最近的等待事件历史,默认每个线程只记录10行记录
  • events_waits_history_long表:记录已经执行完的最近的等待事件历史,默认所有线程的总记录行数为10000行

要注意:等待事件相关配置中,setup_instruments表中绝大部分的等待事件instruments都没有开启(IO相关的等待事件instruments默认大部分已开启),setup_consumers表中waits相关的consumers配置默认没有开启

events_waits_current 表

events_waits_current表包含当前的等待事件信息,每个线程只显示一行最近监视的等待事件的当前状态

在所有包含等待事件行的表中,events_waits_current表是最基础的数据来源。其他包含等待事件数据表在逻辑上是来源于events_waits_current表中的当前事件信息(汇总表除外)。例如,events_waits_history和events_waits_history_long表中的数据是events_waits_current表数据的一个小集合汇总(具体存放多少行数据集合有各自的变量控制)

表记录内容示例(这是一个执行select sleep(100);语句的线程等待事件信息)

[email protected] : performance_schema 12:15:03> select * from events_waits_current where EVENT_NAME='wait/synch/cond/sql/Item_func_sleep::cond'G;

*************************** 1. row ***************************

        THREAD_ID: 46

        EVENT_ID: 140

    END_EVENT_ID: NULL

      EVENT_NAME: wait/synch/cond/sql/Item_func_sleep::cond

          SOURCE: item_func.cc:5261

      TIMER_START: 14128809267002592

        TIMER_END: 14132636159944419

      TIMER_WAIT: 3826892941827

            SPINS: NULL

    OBJECT_SCHEMA: NULL

      OBJECT_NAME: NULL

      INDEX_NAME: NULL

      OBJECT_TYPE: NULL

OBJECT_INSTANCE_BEGIN: 140568905519072

NESTING_EVENT_ID: 116

NESTING_EVENT_TYPE: STATEMENT

        OPERATION: timed_wait

  NUMBER_OF_BYTES: NULL

            FLAGS: NULL

1 row in set (0.00 sec)

上面的输出结果中,TIMER_WAIT字段即表示该事件的时间开销,单位是皮秒,在实际的应用场景中,我们可以利用该字段信息进行倒序排序,以便找出时间开销最大的等待事件。

events_waits_current表完整的字段含义如下:

THREAD_ID,EVENT_ID:与事件关联的线程ID和当前事件ID。THREAD_ID和EVENT_ID值构成了该事件信息行的唯一标识(不会有重复的THREAD_ID EVENT_ID值)

END_EVENT_ID:当一个事件正在执行时该列值为NULL,当一个事件执行结束时把该事件的ID更新到该列

EVENT_NAME:产生事件的instruments名称。该名称来自setup_instruments表的NAME字段值

SOURCE:产生该事件的instruments所在的源文件名称以及检测到该事件发生点的代码行号。您可以查看源代码来确定涉及的代码。例如,如果互斥锁、锁被阻塞,您可以检查发生这种情况的上下文环境

TIMER_START,TIMER_END,TIMER_WAIT:事件的时间信息。单位皮秒(万亿分之一秒)。 TIMER_START和TIMER_END值表示事件开始和结束时间。 TIMER_WAIT是事件经过时间(即事件执行了多长时间)

  • 如果事件未执行完成,则TIMER_END为当前计时器时间值(当前时间),TIMER_WAIT为目前为止所经过的时间(TIMER_END - TIMER_START)
  • 如果采集该事件的instruments配置项TIMED = NO,则不会收集事件的时间信息,TIMER_START,TIMER_END和TIMER_WAIT在这种情况下均记录为NULL

SPINS:对于互斥量和自旋次数。如果该列值为NULL,则表示代码中没有使用自旋或者说自旋没有被监控起来

OBJECT_SCHEMA,OBJECT_NAME,OBJECT_TYPE,OBJECT_INSTANCE_BEGIN:这些列标识了一个正在被执行的对象,所以这些列记录的信息含义需要看对象是什么类型,下面按照不同对象类型分别对这些列的含义进行说明:

*** 对于同步对象(cond,mutex,rwlock):**

* 1)、OBJECT_SCHEMA,OBJECT_NAME和OBJECT_TYPE列值都为NULL

* 2)、OBJECT_INSTANCE_BEGIN列是内存中同步对象的地址。OBJECT_INSTANCE_BEGIN除了不同的值标记不同的对象之外,其值本身没有意义。但OBJECT_INSTANCE_BEGIN值可用于调试。例如,它可以与GROUP BY OBJECT_INSTANCE_BEGIN子句一起使用来查看1,000个互斥体(例如:保护1,000个页或数据块)上的负载是否是均匀分布还是发生了一些瓶颈。如果在日志文件或其他调试、性能工具中看到与该语句查看的结果中有相同的对象地址,那么,在你分析性能问题时,可以把这个语句查看到的信息与其他工具查看到的信息关联起来。

*** 对于文件I/O对象:**

* 1)、OBJECT_SCHEMA列值为NULL
* 2)、OBJECT_NAME列是文件名
* 3)、OBJECT_TYPE列为FILE
* 4)、OBJECT_INSTANCE_BEGIN列是内存中的地址,解释同上

*** 对于套接字对象:**

* 1)、OBJECT_NAME列是套接字的IP:PORT值

* 2)、OBJECT_INSTANCE_BEGIN列是内存中的地址,解释同上

*** 对于表I/O对象:**

* 1)、OBJECT_SCHEMA列是包含该表的库名称

* 2)、OBJECT_NAME列是表名

* 3)、OBJECT_TYPE列值对于基表或者TEMPORARY TABLE临时表,该值是table,注意:对于在join查询中select_type为DERIVED,subquery等的表可能不记录事件信息也不进行统计

* 4)、OBJECT_INSTANCE_BEGIN列是内存中的地址,解释同上

INDEX_NAME:表示使用的索引的名称。PRIMARY表示使用到了主键。 NULL表示没有使用索引

NESTING_EVENT_ID:表示该行信息中的EVENT_ID事件是嵌套在哪个事件中,即父事件的EVENT_ID

NESTING_EVENT_TYPE:表示该行信息中的EVENT_ID事件嵌套的事件类型。有效值有:TRANSACTION,STATEMENT,STAGE或WAIT,即父事件的事件类型,如果为TRANSACTION则需要到事务事件表中找对应NESTING_EVENT_ID值的事件,其他类型同理

OPERATION:执行的操作类型,如:lock、read、write、timed_wait

NUMBER_OF_BYTES:操作读取或写入的字节数或行数。对于文件IO等待,该列值表示字节数;对于表I/O等待(wait/io/table/sql/handler instruments的事件),该列值表示行数。如果值大于1,则表示该事件对应一个批量I/O操作。以下分别对单个表IO和批量表IO的区别进行描述:

  • MySQL的join查询使用嵌套循环实现。performance_schema instruments的作用是在join查询中提供对每个表的扫描行数和执行时间进行统计。示例:join查询语句:SELECT … FROM t1 JOIN t2 ON … JOIN t3 ON …,假设join顺序是t1,t2,t3
  • 在join查询中,一个表在查询时与其他表展开联结查询之后,该表的扫描行数可能增加也可能减少,例如:如果t3表扇出大于1,则大多数row fetch操作都是针对t3表,假如join查询从t1表访问10行记录,然后使用t1表驱动查询t2表,t1表的每一行都会扫描t2表的20行记录,然后使用t2表驱动查询t3表,t2表的每一行都会扫描t3表的30行记录,那么,在使用单行输出时,instruments统计操作的事件信息总行数为:10 (10 * 20) (10 * 20 * 30)= 6210
  • 通过对表中行扫描时的instruments统计操作进行聚合(即,每个t1和t2的扫描行数在instruments统计中可以算作一个批量组合),这样就可以减少instruments统计操作的数量。通过批量I/O输出方式,performance_schema每次对最内层表t3的扫描减少为一个事件统计信息而不是每一行扫描都生成一个事件信息,此时对于instruments统计操作的事件行数量减少到:10 (10 * 20) (10 * 20)= 410,这样在该join查询中对于performance_schema中的行统计操作就减少了93%,批量输出策略通过减少输出行数量来显着降低表I/O的performance_schema统计开销。但是相对于每行数据都单独执行统计操作,会损失对时间统计的准确度。在join查询中,批量I/O统计的时间包括用于连接缓冲、聚合和返回行到客户端的操作所花费的时间(即就是整个join语句的执行时间)

FLAGS:留作将来使用

PS:events_waits_current表允许使用TRUNCATE TABLE语句

events_waits_history 表

events_waits_history表包含每个线程最近的N个等待事件。 在server启动时,N的值会自动调整。 如果要显式设置这个N大小,可以在server启动之前调整系统参数performance_schema_events_waits_history_size的值。 等待事件需要执行结束时才被添加到events_waits_history表中(没有结束时保存在events_waits_current表)。当添加新事件到events_waits_history表时,如果该表已满,则会丢弃每个线程较旧的事件

events_waits_history与events_waits_current表定义相同

PS:允许执行TRUNCATE TABLE语句

events_waits_history_long 表

events_waits_history_long表包含最近的N个等待事件(所有线程的事件)。在server启动时,N的值会自动调整。 如果要显式设置这个N大小,可以在server启动之前调整系统参数

performance_schema_events_waits_history_long_size的值。等待事件需要执行结束时才会被添加到events_waits_history_long表中(没有结束时保存在events_waits_current表),当添加新事件到events_waits_history_long表时,如果该表已满,则会丢弃该表中较旧的事件。

events_waits_history_long与events_waits_current表结构相同

PS:允许使用TRUNCATE TABLE语句

| 阶段事件表

阶段事件记录表与等待事件记录表一样,也有三张表,这些表记录了当前与最近在MySQL实例中发生了哪些阶段事件,时间消耗是多少。阶段指的是语句执行过程中的步骤,例如:parsing 、opening tables、filesort操作等。

在以往我们查看语句执行的阶段状态,常常使用SHOW PROCESSLIST语句或查询INFORMATION_SCHEMA.PROCESSLIST表来获得,但processlist方式能够查询到的信息比较有限且转瞬即逝,我们常常需要结合profiling功能来进一步统计分析语句执行的各个阶段的开销等,现在,我们不需要这么麻烦,直接使用performance_schema的阶段事件就既可以查询到所有的语句执行阶段,也可以查询到各个阶段对应的开销,因为是记录在表中,所以更可以使用SQL语句对这些数据进行排序、统计等操作

要注意:阶段事件相关配置中,setup_instruments表中stage/开头的绝大多数instruments配置默认没有开启(少数stage/开头的instruments除外,如DDL语句执行过程的stage/innodb/alter*开头的instruments默认开启的),setup_consumers表中stages相关的consumers配置默认没有开启

events_stages_current 表

events_stages_current表包含当前阶段事件的监控信息,每个线程一行记录显示线程正在执行的stage事件的状态

在包含stage事件记录的表中,events_stages_current是基准表,包含stage事件记录的其他表(如:events_stages_history和events_stages_history_long表)的数据在逻辑上都来自events_stages_current表(汇总表除外)

表记录内容示例(以下仍然是一个执行select sleep(100);语句的线程,但这里是阶段事件信息)

[email protected] : performance_schema 12:24:40> select * from events_stages_current where EVENT_NAME='stage/sql/User sleep'G;

*************************** 1. row ***************************

    THREAD_ID: 46

      EVENT_ID: 280

  END_EVENT_ID: NULL

    EVENT_NAME: stage/sql/User sleep

        SOURCE: item_func.cc:6056

  TIMER_START: 14645080545642000

    TIMER_END: 14698320697396000

    TIMER_WAIT: 53240151754000

WORK_COMPLETED: NULL

WORK_ESTIMATED: NULL

NESTING_EVENT_ID: 266

NESTING_EVENT_TYPE: STATEMENT

1 row in set (0.00 sec)

以上的输出结果与语句的等待事件形式类似,这里不再赘述,events_stages_current表完整的字段含义如下

THREAD_ID,EVENT_ID:与事件关联的线程ID和当前事件ID,可以使用THREAD_ID和EVENT_ID列值来唯一标识该行,这两行的值作为组合条件时不会出现相同的数据行

END_EVENT_ID:当一个事件开始执行时,对应行记录的该列值被设置为NULL,当一个事件执行结束时,对应的行记录的该列值被更新为该事件的ID

EVENT_NAME:产生事件的instruments的名称。该列值来自setup_instruments表的NAME值。instruments名称可能具有多个部分并形成层次结构,如:"stage/sql/Slave has read all relay log; waiting for more updates",其中stage是*名称,sql是二级名称,Slave has read all relay log; waiting for more updates是第三级名称。详见链接:

https://dev.mysql.com/doc/refman/5.7/en/performance-schema-instrument-naming.html

SOURCE:源文件的名称及其用于检测该事件的代码位于源文件中的行号

TIMER_START,TIMER_END,TIMER_WAIT:事件的时间信息。这些值的单位是皮秒(万亿分之一秒)。 TIMER_START和TIMER_END值表示事件的开始时间和结束时间。TIMER_WAIT是事件执行消耗的时间(持续时间)

  • 如果事件未执行完成,则TIMER_END为当前时间,TIMER_WAIT为当前为止所经过的时间(TIMER_END - TIMER_START)
  • 如果instruments配置表setup_instruments中对应的instruments 的TIMED字段被设置为 NO,则该instruments禁用时间收集功能,那么事件采集的信息记录中,TIMER_START,TIMER_END和TIMER_WAIT字段值均为NULL

WORK_COMPLETED,WORK_ESTIMATED:这些列提供了阶段事件进度信息

  • 表中的WORK_COMPLETED和WORK_ESTIMATED两列,它们共同协作显示每一行的进度显示:

* 1)、WORK_COMPLETED:显示阶段事件已完成的工作单元数

* 2)、WORK_ESTIMATED:显示预计阶段事件将要完成的工作单元数

  • 如果instruments没有提供进度相关的功能,则该instruments执行事件采集时就不会有进度信息显示,WORK_COMPLETED和WORK_ESTIMATED列都会显示为NULL。如果进度信息可用,则进度信息如何显示取决于instruments的执行情况。performance_schema表提供了一个存储进度数据的容器,但不会假设你会定义何种度量单位来使用这些进度数据:

* 1)、“工作单元”是在执行过程中随时间增加而增加的整数度量,例如执行过程中的字节数、行数、文件数或表数。对于特定instruments的“工作单元”的定义留给提供数据的instruments代码

* 2)、WORK_COMPLETED值根据检测的代码不同,可以一次增加一个或多个单元

* 3)、WORK_ESTIMATED值根据检测代码,可能在阶段事件执行过程中发生变化

  • 阶段事件进度指示器的表现行为有以下几种情况:

* 1)、instruments不支持进度:没有可用进度数据, WORK_COMPLETED和WORK_ESTIMATED列都显示为NULL

* 2) 、instruments支持进度但对应的工作负载总工作量不可预估(无限进度):只有WORK_COMPLETED列有意义(因为他显示正在执行的进度显示),WORK_ESTIMATED列此时无效,显示为0,因为没有可预估的总进度数据。通过查询events_stages_current表来监视会话,监控应用程序到目前为止执行了多少工作,但无法报告对应的工作是否接近完成

* 3)、instruments支持进度,总工作量可预估(有限进度):WORK_COMPLETED和WORK_ESTIMATED列值有效。这种类型的进度显示可用于online DDL期间的copy表阶段监视。通过查询events_stages_current表,可监控应用程序当前已经完成了多少工作,并且可以通过WORK_COMPLETED / WORK_ESTIMATED计算的比率来预估某个阶段总体完成百分比

NESTING_EVENT_ID:事件的嵌套事件EVENT_ID值(父事件ID)

NESTING_EVENT_TYPE:嵌套事件类型。有效值为:TRANSACTION,STATEMENT,STAGE,WAIT。阶段事件的嵌套事件通常是statement

对于events_stages_current表允许使用TRUNCATE TABLE语句来进行清理

PS:stage事件拥有一个进度展示功能,我们可以利用该进度展示功能来了解一些长时间执行的SQL的进度百分比,例如:对于需要使用COPY方式执行的online ddl,那么需要copy的数据量是一定的,可以明确的,so..这就可以为"stage/sql/copy to tmp table stage" instruments提供一个有结束边界参照的进度数据信息,这个instruments所使用的工作单元就是需要复制的数据行数,此时WORK_COMPLETED和WORK_ESTIMATED列值都是有效的可用的,两者的计算比例就表示当前copy表完成copy的行数据百分比。

  • 要查看copy表阶段事件的正在执行的进度监视功能,需要打开相关的instruments和consumers,然后查看events_stages_current表,如下:
# 配置相关instruments和consumers

UPDATE setup_instruments SET ENABLED='YES' WHERE NAME='stage/sql/copy to tmp table';

UPDATE setup_consumers SET ENABLED='YES' WHERE NAME LIKE 'events_stages_%';

# 然后在执行ALTER TABLE语句期间,查看events_stages_current表

events_stages_history 表

events_stages_history表包含每个线程最新的N个阶段事件。 在server启动时,N的值会自动调整。 如果要显式设置N值大小,可以在server启动之前设置系统变量performance_schema_events_stages_history_size的值。stages事件在执行结束时才添加到events_stages_history表中。 当添加新事件到events_stages_history表时,如果events_stages_history表已满,则会丢弃对应线程较旧的事件events_stages_history与events_stages_current表结构相同

PS:允许使用TRUNCATE TABLE语句

events_stages_history_long 表

events_stages_history_long表包含最近的N个阶段事件。 在server启动时,N的值会自动调整。 如果要显式设置N值大小,可以在server启动之前设置系统变量performance_schema_events_stages_history_long_size的值。stages事件执行结束时才会添加到events_stages_history_long表中,当添加新事件到events_stages_history_long表时,如果events_stages_history_long表已满,则会丢弃该表中较旧的事件events_stages_history_long与events_stages_current表结构相同

PS:允许使用TRUNCATE TABLE语句

| 语句事件表

语句事件记录表与等待事件记录表一样,也有三张表,这些表记录了当前与最近在MySQL实例中发生了哪些语句事件,时间消耗是多少。记录了各种各样的语句执行产生的语句事件信息。

要注意:语句事件相关配置中,setup_instruments表中statement/*开头的所有instruments配置默认开启,setup_consumers表中statements相关的consumers配置默认开启了events_statements_current、events_statements_history、statements_digest(对应events_statements_summary_by_digest表,详见后续章节)但没有开启events_statements_history_long。

events_statements_current 表

events_statements_current表包含当前语句事件,每个线程只显示一行最近被监视语句事件的当前状态。

在包含语句事件行的表中,events_statements_current当前事件表是基础表。其他包含语句事件表中的数据在逻辑上来源于当前事件表(汇总表除外)。例如:events_statements_history和events_statements_history_long表是最近的语句事件历史的集合,events_statements_history表中每个线程默认保留10行事件历史信息,events_statements_history_long表中默认所有线程保留10000行事件历史信息

表记录内容示例(以下信息仍然来自select sleep(100);语句的语句事件信息)

[email protected] : performance_schema 12:36:35> select * from events_statements_current where SQL_TEXT='select sleep(100)'G;

*************************** 1. row ***************************

          THREAD_ID: 46

          EVENT_ID: 334

      END_EVENT_ID: NULL

        EVENT_NAME: statement/sql/select

            SOURCE: socket_connection.cc:101

        TIMER_START: 15354770719802000

          TIMER_END: 15396587017809000

        TIMER_WAIT: 41816298007000

          LOCK_TIME: 0

          SQL_TEXT: select sleep(100)

            DIGEST: NULL

        DIGEST_TEXT: NULL

    CURRENT_SCHEMA: NULL

        OBJECT_TYPE: NULL

      OBJECT_SCHEMA: NULL

        OBJECT_NAME: NULL

OBJECT_INSTANCE_BEGIN: NULL

        MYSQL_ERRNO: 0

  RETURNED_SQLSTATE: NULL

      MESSAGE_TEXT: NULL

            ERRORS: 0

          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)

以上的输出结果与语句的等待事件形式类似,这里不再赘述,events_statements_current表完整的字段含义如下:

THREAD_ID,EVENT_ID:与事件关联的线程号和事件启动时的事件编号,可以使用THREAD_ID和EVENT_ID列值来唯一标识该行,这两行的值作为组合条件时不会出现相同的数据行

END_EVENT_ID:当一个事件开始执行时,对应行记录的该列值被设置为NULL,当一个事件执行结束时,对应的行记录的该列值被更新为该事件的ID

EVENT_NAME:产生事件的监视仪器的名称。该列值来自setup_instruments表的NAME值。对于SQL语句,EVENT_NAME值最初的instruments是statement/com/Query,直到语句被解析之后,会更改为更合适的具体instruments名称,如:statement/sql/insert

SOURCE:源文件的名称及其用于检测该事件的代码位于源文件中的行号,您可以检查源代码来确定涉及的代码

TIMER_START,TIMER_END,TIMER_WAIT:事件的时间信息。这些值的单位是皮秒(万亿分之一秒)。 TIMER_START和TIMER_END值表示事件的开始时间和结束时间。TIMER_WAIT是事件执行消耗的时间(持续时间)

  • 如果事件未执行完成,则TIMER_END为当前时间,TIMER_WAIT为当前为止所经过的时间(TIMER_END - TIMER_START)。
  • 如果监视仪器配置表setup_instruments中对应的监视器TIMED字段被设置为 NO,则不会收集该监视器的时间信息,那么对于该事件采集的信息记录中,TIMER_START,TIMER_END和TIMER_WAIT字段值均为NULL

LOCK_TIME:等待表锁的时间。该值以微秒进行计算,但最终转换为皮秒显示,以便更容易与其他performance_schema中的计时器进行比较

SQL_TEXT:SQL语句的文本。如果该行事件是与SQL语句无关的command事件,则该列值为NULL。默认情况下,语句最大显示长度为1024字节。如果要修改,则在server启动之前设置系统变量performance_schema_max_sql_text_length的值

DIGEST:语句摘要的MD5 hash值,为32位十六进制字符串,如果在setup_consumers表中statement_digest配置行没有开启,则语句事件中该列值为NULL

DIGEST_TEXT:标准化转换过的语句摘要文本,如果setup_consumers表中statements_digest配置行没有开启,则语句事件中该列值为NULL。performance_schema_max_digest_length系统变量决定着在存入该表时的最大摘要语句文本的字节长度(默认为1024字节),要注意:用于计算摘要语句文本的原始语句文本字节长度由系统变量max_digest_length控制,而存入表中的字节长度由系统变量performance_schema_max_digest_length控制,所以,如果performance_schema_max_digest_length小于max_digest_length时,计算出的摘要语句文本如果大于了performance_schema_max_digest_length定义的长度会被截断

CURRENT_SCHEMA:语句使用的默认数据库(使用use db_name语句即可指定默认数据库),如果没有则为NULL

OBJECT_SCHEMA,OBJECT_NAME,OBJECT_TYPE:对于嵌套语句(存储程序最终是通过语句调用的,所以如果一个语句是由存储程序调用的,虽然说这个语句事件是嵌套在存储程序中的,但是实际上对于事件类型来讲,仍然是嵌套在语句事件中),这些列包含有关父语句的信息。如果不是嵌套语句或者是父语句本身产生的事件,则这些列值为NULL

OBJECT_INSTANCE_BEGIN:语句的唯一标识,该列值是内存中对象的地址

MYSQL_ERRNO:语句执行的错误号,此值来自代码区域的语句诊断区域

RETURNED_SQLSTATE:语句执行的SQLSTATE值,此值来自代码区域的语句诊断区域

MESSAGE_TEXT:语句执行的具体错误信息,此值来自代码区域的语句诊断区域

ERRORS:语句执行是否发生错误。如果SQLSTATE值以00(完成)或01(警告)开始,则该列值为0。其他任何SQLSTATE值时,该列值为1

WARNINGS:语句警告数,此值来自代码区域的语句诊断区域

ROWS_AFFECTED:受该语句影响的行数。有关“受影响”的含义的描述,参见连接:https://dev.mysql.com/doc/refman/5.7/en/mysql-affected-rows.html

  • 使用mysql_query()或mysql_real_query()函数执行语句后,可能会立即调用mysql_affected_rows()函数。如果是UPDATE,DELETE或INSERT,则返回最后一条语句更改、删除、插入的行数。对于SELECT语句,mysql_affected_rows()的工作方式与mysql_num_rows()一样(在执行结果最后返回的信息中看不到effected统计信息)
  • 对于UPDATE语句,受影响的行值默认为实际更改的行数。如果在连接到mysqld时指定了CLIENT_FOUND_ROWS标志给mysql_real_connect()函数,那么affected-rows的值是“found”的行数。即WHERE子句匹配到的行数
  • 对于REPLACE语句,如果发生新旧行替换操作,则受影响的行值为2,因为在这种情况下,实际上是先删除旧值,后插入新值两个行操作
  • 对于INSERT … ON DUPLICATE KEY UPDATE语句,如果行作为新行插入,则每行的affected计数为1,如果发生旧行更新为新行则每行affected计数为2,如果没有发生任何插入和更新,则每行的affected计数为0 (但如果指定了CLIENT_FOUND_ROWS标志,则没有发生任何的插入和更新时,即set值就为当前的值时,每行的受影响行值计数为1而不是0)
  • 在存储过程的CALL语句调用之后,mysql_affected_rows()返回的影响行数是存储程序中的最后一个语句执行的影响行数值,如果该语句返回-1,则存储程序最终返回0受影响。所以在存储程序执行时返回的影响行数并不可靠,但是你可以自行在存储程序中实现一个计数器变量在SQL级别使用ROW_COUNT()来获取各个语句的受影响的行值并相加,最终通过存储程序返回这个变量值。
  • 在MySQL 5.7中,mysql_affected_rows()为更多的语句返回一个有意义的值。

* 1)、对于DDL语句,row_count()函数返回0,例如:CREATE TABLE、ALTER TABLE、DROP TABLE之类的语句

* 2)、对于除SELECT之外的DML语句:row_count()函数返回实际数据变更的行数。例如:UPDATE、INSERT、DELETE语句,现在也适用于LOAD DATA INFILE之类的语句,大于0的返回值表示DML语句做了数据变更,如果返回为0,则表示DML语句没有做任何数据变更,或者没有与where子句匹配的记录,如果返回-1则表示语句返回了错误

* 3)、对于SELECT语句:row_count()函数返回-1,例如:SELECT * FROM t1语句,ROW_COUNT()返回-1(对于select语句,在调用mysql_store_result()之前调用了mysql_affected_rows()返回了)。但是对于SELECT * FROM t1 INTO OUTFILE‘file_name‘这样的语句,ROW_COUNT()函数将返回实际写入文件中的数据行数

* 4)、对于SIGNAL语句:row_count()函数返回0

* 5)、因为mysql_affected_rows()返回的是一个无符号值,所以row_count()函数返回值小于等于0时都转换为0值返回或者不返回给effected值,row_count()函数返回值大于0时则返回给effected值

ROWS_SENT:语句返回给客户端的数据行数

ROWS_EXAMINED:在执行语句期间从存储引擎读取的数据行数

CREATED_TMP_DISK_TABLES:像Created_tmp_disk_tables状态变量一样的计数值,但是这里只用于这个事件中的语句统计而不针对全局、会话级别

CREATED_TMP_TABLES:像Created_tmp_tables状态变量一样的计数值,但是这里只用于这个事件中的语句统计而不针对全局、会话级别

SELECT_FULL_JOIN:像Select_full_join状态变量一样的计数值,但是这里只用于这个事件中的语句统计而不针对全局、会话级别

SELECT_FULL_RANGE_JOIN:像Select_full_range_join状态变量一样的计数值,但是这里只用于这个事件中的语句统计而不针对全局、会话级别

SELECT_RANGE:就像Select_range状态变量一样的计数值,但是这里只用于这个事件中的语句统计而不针对全局、会话级别

SELECT_RANGE_CHECK:像Select_range_check状态变量一样的计数值,但是这里只用于这个事件中的语句统计而不针对全局、会话级别

SELECT_SCAN:像Select_scan状态变量一样的计数值,但是这里只用于这个事件中的语句统计而不针对全局、会话级别

SORT_MERGE_PASSES:像Sort_merge_passes状态变量一样的计数值,但是这里只用于这个事件中的语句统计而不针对全局、会话级别

SORT_RANGE:像Sort_range状态变量一样的计数值,但是这里只用于这个事件中的语句统计而不针对全局、会话级别

SORT_ROWS:像Sort_rows状态变量一样的计数值,但是这里只用于这个事件中的语句统计而不针对全局、会话级别

SORT_SCAN:像Sort_scan状态变量一样的计数值,但是这里只用于这个事件中的语句统计而不针对全局、会话级别

NO_INDEX_USED:如果语句执行表扫描而不使用索引,则该列值为1,否则为0

NO_GOOD_INDEX_USED:如果服务器找不到用于该语句的合适索引,则该列值为1,否则为0

NESTING_EVENT_ID,NESTING_EVENT_TYPE,NESTING_EVENT_LEVEL:这三列与其他列结合一起使用,为*(未知抽象的语句或者说是父语句)语句和嵌套语句(在存储的程序中执行的语句)提供以下事件信息

  • 对于*语句:

OBJECT_TYPE = NULL,OBJECT_SCHEMA = NULL,OBJECT_NAME = NULL,NESTING_EVENT_ID = NULL,NESTING_EVENT_TYPE = NULL,NESTING_LEVEL = 0

  • 对于嵌套语句:OBJECT_TYPE =父语句对象类型,OBJECT_SCHEMA =父语句数据库级名称,OBJECT_NAME =父语句表级对象名称,NESTING_EVENT_ID =父语句EVENT_ID,NESTING_EVENT_TYPE =‘STATEMENT‘,NESTING_LEVEL =父语句NESTING_LEVEL加一,例如:1,表示父语句的下一层嵌套语句

允许使用TRUNCATE TABLE语句

events_statements_history 表

events_statements_history表包含每个线程最新的N个语句事件。 在server启动时,N的值会自动调整。 要显式设置N的大小,可以在server启动之前设置系统变量performance_schema_events_statements_history_size的值。 statement事件执行完成时才会添加到该表中。 当添加新事件到该表时,如果对应线程的事件在该表中的配额已满,则会丢弃对应线程的较旧的事件

events_statements_history与events_statements_current表结构相同

PS:允许使用TRUNCATE TABLE语句

events_statements_history_long 表

events_statements_history_long表包含最近的N个语句事件。在server启动时,N的值会自动调整。 要显式设置N的大小,可以在server启动之前设置系统变量performance_schema_events_statements_history_long_size的值。 statement事件需要执行结束时才会添加到该表中。 当添加新事件到该表时,如果该表的全局配额已满,则会丢弃该表中较旧的事件

events_statements_history_long与events_statements_current表结构相同

PS:允许使用TRUNCATE TABLE语句

事务事件表

事务事件记录表与等待事件记录表一样,也有三张表,这些表记录了当前与最近在MySQL实例中发生了哪些事务事件,时间消耗是多少

要注意:事务事件相关配置中,setup_instruments表中只有一个名为transaction的instrument,默认关闭,setup_consumers表中transactions相关的consumers配置默认关闭了

events_transactions_current 表

events_transactions_current表包含当前事务事件信息,每个线程只保留一行最近事务的事务事件

在包含事务事件信息的表中,events_transactions_current是基础表。其他包含事务事件信息的表中的数据逻辑上来源于当前事件表。例如:events_transactions_history和events_transactions_history_long表分别包含每个线程最近10行事务事件信息和全局最近10000行事务事件信息

表记录内容示例(以下信息来自对某表执行了一次select等值查询的事务事件信息)

[email protected] : performance_schema 12:50:10> select * from events_transactions_currentG;

*************************** 1. row ***************************

                  THREAD_ID: 46

                  EVENT_ID: 38685

              END_EVENT_ID: 38707

                EVENT_NAME: transaction

                      STATE: COMMITTED

                    TRX_ID: 422045139261264

                      GTID: AUTOMATIC

              XID_FORMAT_ID: NULL

                  XID_GTRID: NULL

                  XID_BQUAL: NULL

                  XA_STATE: NULL

                    SOURCE: handler.cc:1421

                TIMER_START: 16184509764409000

                  TIMER_END: 16184509824175000

                TIMER_WAIT: 59766000

                ACCESS_MODE: READ WRITE

            ISOLATION_LEVEL: READ COMMITTED

                AUTOCOMMIT: YES

      NUMBER_OF_SAVEPOINTS: 0

NUMBER_OF_ROLLBACK_TO_SAVEPOINT: 0

NUMBER_OF_RELEASE_SAVEPOINT: 0

      OBJECT_INSTANCE_BEGIN: NULL

          NESTING_EVENT_ID: 38667

        NESTING_EVENT_TYPE: STATEMENT

1 row in set (0.00 sec)

以上的输出结果与语句的等待事件形式类似,这里不再赘述,events_transactions_current表完整字段含义如下:

THREAD_ID,EVENT_ID:与事件关联的线程号和事件启动时的事件编号,可以使用THREAD_ID和EVENT_ID列值来唯一标识该行,这两行的值作为组合条件时不会出现相同的数据行

END_EVENT_ID:当一个事件开始执行时,对应行记录的该列值被设置为NULL,当一个事件执行结束时,对应的行记录的该列值被更新为该事件的ID

EVENT_NAME:收集该事务事件的instruments的名称。来自setup_instruments表的NAME列值

STATE:当前事务状态。有效值为:ACTIVE(执行了START TRANSACTION或BEGIN语句之后,事务未提交或未回滚之前)、COMMITTED(执行了COMMIT之后)、ROLLED BACK(执行了ROLLBACK语句之后)

TRX_ID:未使用,字段值总是为NULL

GTID:包含gtid_next系统变量的值,其值可能是格式为:UUID:NUMBER的GTID,也可能是:ANONYMOUS、AUTOMATIC。对于AUTOMATIC列值的事务事件,GTID列在事务提交和对应事务的GTID实际分配时都会进行更改(如果gtid_mode系统变量为ON或ON_PERMISSIVE,则GTID列将更改为事务的GTID,如果gtid_mode为OFF或OFF_PERMISSIVE,则GTID列将更改为ANONYMOUS)

XID_FORMAT_ID,XID_GTRID和XID_BQUAL:XA事务标识符的组件。关于XA事务语法详见链接:https://dev.mysql.com/doc/refman/5.7/en/xa-statements.html

XA_STATE:XA事务的状态。有效值为:ACTIVE(执行了XA START之后,未执行其他后续XA语句之前)、IDLE(执行了XA END语句之后,未执行其他后续XA语句之前)、PREPARED(执行了XA PREPARE语句之后,未执行其他后续XA语句之前)、ROLLED BACK(执行了XA ROLLBACK语句之后,未执行其他后续XA语句之前)、COMMITTED(执行了XA COMMIT语句之后)

SOURCE:源文件的名称及其用于检测该事件的代码位于源文件中的行号,您可以检查源代码来确定涉及的代码

TIMER_START,TIMER_END,TIMER_WAIT:事件的时间信息。这些值的单位是皮秒(万亿分之一秒)。 TIMER_START和TIMER_END值表示事件的开始时间和结束时间。TIMER_WAIT是事件执行消耗的时间(持续时间)

  • 如果事件未执行完成,则TIMER_END为当前时间,TIMER_WAIT为当前为止所经过的时间(TIMER_END - TIMER_START)
  • 如果监视仪器配置表setup_instruments中对应的监视器TIMED字段被设置为 NO,则不会收集该监视器的时间信息,那么对于该事件采集的信息记录中,TIMER_START,TIMER_END和TIMER_WAIT字段值均为NULL

ACCESS_MODE:事务访问模式。有效值为:READ ONLY或READ WRITE

ISOLATION_LEVEL:事务隔离级别。有效值为:REPEATABLE READ、READ COMMITTED、READ UNCOMMITTED、SERIALIZABLE

AUTOCOMMIT:在事务开始时是否启用了自动提交模式,如果启用则为YES,没有启用则为NO

NUMBER_OF_SAVEPOINTS,NUMBER_OF_ROLLBACK_TO_SAVEPOINT,NUMBER_OF_RELEASE_SAVEPOINT:在事务内执行的SAVEPOINT,ROLLBACK TO SAVEPOINT和RELEASE SAVEPOINT语句的数量

OBJECT_INSTANCE_BEGIN:未使用,字段值总是为NULL

NESTING_EVENT_ID:嵌套事务事件的父事件EVENT_ID值

NESTING_EVENT_TYPE:嵌套事件类型。有效值为:TRANSACTION、STATEMENT、STAGE、WAIT (由于事务无法嵌套,因此该列值不会出现TRANSACTION)

允许使用TRUNCATE TABLE语句

events_transactions_history 表

events_transactions_history表包含每个线程最近的N个事务事件。 在server启动时,N的值会自动调整。 要显式设置N的大小,可以在server启动之前设置系统变量

performance_schema_events_transactions_history_size的值。事务事件未执行完成之前不会添加到该表中。当有新的事务事件添加到该表时,如果该表已满,则会丢弃对应线程较旧的事务事件

events_transactions_history与events_transactions_current表结构相同

PS:允许使用TRUNCATE TABLE语句

events_transactions_history_long 表

events_transactions_history_long表包含全局最近的N个事务事件。在server启动时,N的值会自动调整。 要显式设置N的大小,可以在server启动之前设置系统变量

performance_schema_events_transactions_history_long_size的值。事务事件在执行完之前不会添加到该表中。当添加新事务事件时,如果该表已满,则会丢弃较旧的事件

events_transactions_history_long与events_transactions_current表结构相同

PS:允许使用TRUNCATE TABLE语句