性能模式会对语句执行进行检测。语句事件发生在事件层次结构的较高层级。在事件层次结构中,等待事件嵌套在阶段事件中,阶段事件嵌套在语句事件中,语句事件嵌套在事务事件中。
以下表存储语句事件:
events_statements_current
:每个线程的当前语句事件。events_statements_history
:每个线程已结束的最近语句事件。events_statements_history_long
:全局(所有线程)已结束的最近语句事件。prepared_statements_instances
:预处理语句实例和统计信息
以下部分介绍语句事件表。还有一些汇总表汇总了有关语句事件的信息;请参阅 第 29.12.20.3 节,“语句汇总表”。
有关三个 events_statements_
事件表之间关系的更多信息,请参阅 第 29.9 节,“性能模式当前和历史事件表”。xxx
配置语句事件收集
要控制是否收集语句事件,请设置相关 Instrument 和 Consumer 的状态。
setup_instruments
表包含名称以statement
开头的 Instrument。使用这些 Instrument 可以启用或禁用各个语句事件类的收集。setup_consumers
表包含名称与当前和历史语句事件表名称以及语句摘要 Consumer 相对应的 Consumer 值。使用这些 Consumer 可以过滤语句事件和语句摘要的收集。
默认情况下,语句 Instrument 处于启用状态,events_statements_current
、events_statements_history
和 statements_digest
语句 Consumer 也处于启用状态。
mysql> SELECT NAME, ENABLED, TIMED
FROM performance_schema.setup_instruments
WHERE NAME LIKE 'statement/%';
+---------------------------------------------+---------+-------+
| NAME | ENABLED | TIMED |
+---------------------------------------------+---------+-------+
| statement/sql/select | YES | YES |
| statement/sql/create_table | YES | YES |
| statement/sql/create_index | YES | YES |
...
| statement/sp/stmt | YES | YES |
| statement/sp/set | YES | YES |
| statement/sp/set_trigger_field | YES | YES |
| statement/scheduler/event | YES | YES |
| statement/com/Sleep | YES | YES |
| statement/com/Quit | YES | YES |
| statement/com/Init DB | YES | YES |
...
| statement/abstract/Query | YES | YES |
| statement/abstract/new_packet | YES | YES |
| statement/abstract/relay_log | YES | YES |
+---------------------------------------------+---------+-------+
mysql> SELECT *
FROM performance_schema.setup_consumers
WHERE NAME LIKE '%statements%';
+--------------------------------+---------+
| NAME | ENABLED |
+--------------------------------+---------+
| events_statements_current | YES |
| events_statements_history | YES |
| events_statements_history_long | NO |
| statements_digest | YES |
+--------------------------------+---------+
要在服务器启动时控制语句事件收集,请在 my.cnf
文件中使用如下所示的行:
启用
[mysqld] performance-schema-instrument='statement/%=ON' performance-schema-consumer-events-statements-current=ON performance-schema-consumer-events-statements-history=ON performance-schema-consumer-events-statements-history-long=ON performance-schema-consumer-statements-digest=ON
禁用
[mysqld] performance-schema-instrument='statement/%=OFF' performance-schema-consumer-events-statements-current=OFF performance-schema-consumer-events-statements-history=OFF performance-schema-consumer-events-statements-history-long=OFF performance-schema-consumer-statements-digest=OFF
要在运行时控制语句事件收集,请更新 setup_instruments
和 setup_consumers
表。
启用
UPDATE performance_schema.setup_instruments SET ENABLED = 'YES', TIMED = 'YES' WHERE NAME LIKE 'statement/%'; UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME LIKE '%statements%';
禁用
UPDATE performance_schema.setup_instruments SET ENABLED = 'NO', TIMED = 'NO' WHERE NAME LIKE 'statement/%'; UPDATE performance_schema.setup_consumers SET ENABLED = 'NO' WHERE NAME LIKE '%statements%';
要仅收集特定语句事件,请仅启用相应的语句 Instrument。要仅为特定语句事件表收集语句事件,请启用语句 Instrument,但仅启用与所需表对应的语句 Consumer。
有关配置事件收集的更多信息,请参阅 第 29.3 节,“性能模式启动配置” 和 第 29.4 节,“性能模式运行时配置”。
语句监控
语句监控从服务器发现线程上有活动请求的那一刻开始,到所有活动停止的那一刻结束。 通常,这意味着从服务器从客户端获取第一个数据包到服务器完成发送响应的时间。 存储程序中的语句与其他语句一样受到监控。
当 Performance Schema 检测请求(服务器命令或 SQL 语句)时,它使用的检测名称从更一般(或 “抽象”)到更具体,直到到达最终的检测名称。
最终的检测名称对应于服务器命令和 SQL 语句
服务器命令对应于
mysql_com.h
头文件中定义并在sql/sql_parse.cc
中处理的COM_
代码。 例如xxx
COM_PING
和COM_QUIT
。 命令的检测名称以statement/com
开头,例如statement/com/Ping
和statement/com/Quit
。SQL 语句以文本形式表示,例如
DELETE FROM t1
或SELECT * FROM t2
。 SQL 语句的检测名称以statement/sql
开头,例如statement/sql/delete
和statement/sql/select
。
一些最终的检测名称特定于错误处理
statement/com/Error
用于记录服务器收到的带外消息。 它可用于检测客户端发送的服务器无法理解的命令。 这可能有助于识别配置错误或使用比服务器更新版本的 MySQL 的客户端,或尝试攻击服务器的客户端。statement/sql/error
用于记录无法解析的 SQL 语句。 它可用于检测客户端发送的格式错误的查询。 无法解析的查询与已解析但由于执行期间出错而失败的查询不同。 例如,SELECT * FROM
格式错误,并且使用statement/sql/error
检测。 相比之下,SELECT *
可以解析但会因No tables used
错误而失败。 在这种情况下,将使用statement/sql/select
并且语句事件包含指示错误性质的信息。
可以从以下任何来源获取请求
作为来自客户端的命令或语句请求,客户端将请求作为数据包发送
作为从副本上的中继日志读取的语句字符串
作为来自事件调度程序的事件
请求的详细信息最初是未知的,Performance Schema 会根据请求的来源,按顺序从抽象检测名称进行到具体检测名称。
对于从客户端收到的请求
当服务器在套接字级别检测到新数据包时,将使用抽象检测名称
statement/abstract/new_packet
启动新语句。当服务器读取数据包编号时,它会更了解接收到的请求类型,并且 Performance Schema 会优化检测名称。 例如,如果请求是
COM_PING
数据包,则检测名称将变为statement/com/Ping
,并且这是最终名称。 如果请求是COM_QUERY
数据包,则已知它对应于 SQL 语句,但不知道特定类型的语句。 在这种情况下,检测从一个抽象名称更改为更具体但仍然是抽象的名称,statement/abstract/Query
,并且该请求需要进一步分类。如果请求是一个语句,则读取语句文本并将其提供给解析器。 解析后,将知道确切的语句类型。 例如,如果请求是
INSERT
语句,则 Performance Schema 会将检测名称从statement/abstract/Query
优化为statement/sql/insert
,这是最终名称。
对于作为语句从副本上的中继日志读取的请求
中继日志中的语句存储为文本,并按原样读取。 没有网络协议,因此不使用
statement/abstract/new_packet
检测。 相反,初始检测是statement/abstract/relay_log
。解析语句后,将知道确切的语句类型。 例如,如果请求是
INSERT
语句,则 Performance Schema 会将检测名称从statement/abstract/Query
优化为statement/sql/insert
,这是最终名称。
前面的描述仅适用于基于语句的复制。 对于基于行的复制,可以检测副本在处理行更改时执行的表 I/O,但中继日志中的行事件不会显示为离散语句。
对于从事件调度程序接收的请求
使用名称 statement/scheduler/event
检测事件执行。 这是最终名称。
事件体中执行的语句使用 statement/sql/*
名称进行检测,而不使用任何前面的抽象检测。 事件是一个存储程序,存储程序在执行之前会在内存中进行预编译。 因此,在运行时没有解析,并且每个语句的类型在执行时都是已知的。
在事件体中执行的语句是子语句。 例如,如果事件执行 INSERT
语句,则事件本身的执行是父级,使用 statement/scheduler/event
进行检测,而 INSERT
是子级,使用 statement/sql/insert
进行检测。 父/子关系存在于单独检测的操作 之间。 这与在单个检测操作 内 发生的优化顺序不同,从抽象检测名称到最终检测名称。
为了收集语句的统计信息,仅启用用于单个语句类型的最终 statement/sql/*
检测是不够的。 还必须启用抽象 statement/abstract/*
检测。 这通常不应该成为问题,因为默认情况下所有语句检测都是启用的。 但是,选择性地启用或禁用语句检测的应用程序必须考虑到禁用抽象检测也会禁用对各个语句检测的统计信息收集。 例如,要收集 INSERT
语句的统计信息,必须启用 statement/sql/insert
,但也必须启用 statement/abstract/new_packet
和 statement/abstract/Query
。 同样,为了对复制的语句进行检测,必须启用 statement/abstract/relay_log
。
不会为抽象检测(例如 statement/abstract/Query
)聚合统计信息,因为没有语句会被归类为最终语句名称为抽象检测。