有趣的statement stack

打印 上一主题 下一主题

主题 1115|帖子 1115|积分 3345

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
引子

在使用events_statements_current的过程中发现,同一线程在同一时刻,可能有多条记录,与直观感觉不太一样,于是跟踪了一下内部实现,有了本文。
STATEMENT STACK的定义

STATEMENT STACK 是events_statements_current表被后用于存储当前会话执行语句堆栈的数据结构。
在MySQL8中,相关定义如下:
  1. /** Max size of the statements stack. */
  2. uint statement_stack_max;
  3. /** nested statement lost */
  4. uint nested_statement_lost;
  5. struct PFS_ALIGNED PFS_thread : PFS_connection_slice {
  6. //...
  7. /** Size of @c m_events_statements_stack. */
  8.   uint m_events_statements_count;
  9.   PFS_events_statements *m_statement_stack;
  10. //...
  11. }
复制代码
其中:

  • m_statement_stack 语句堆栈
  • m_events_statements_count 语句堆栈栈顶指针
  • statement_stack_max 存储允许存储的最大语句数量
  • nested_statement_lost 存储丢失的语句数量
STATEMENT STACK相关小实验

1) 创建测试存储过程

存储过程的功能主要是:人为等待10秒左右
  1. -- 保存为:stat_stack.sql
  2. USE d1;
  3. set sql_mode=oracle;
  4. set global log_bin_trust_function_creators = 1;
  5. DELIMITER $$
  6. CREATE OR REPLACE PROCEDURE p1(a INT DEFAULT 1)
  7. AS
  8. BEGIN
  9.     SELECT a, SLEEP(a);
  10. END$$
  11. CALL p1(10);
复制代码
2) 启动终端1输入命令:
  1. USE PERFORMANCE_SCHEMA;
  2. -- 确认采集打开
  3. UPDATE setup_consumers SET ENABLED='YES' WHERE name = 'events_statements_current';
  4. -- Query OK, 0 rows affected (0.00 sec)
  5. -- Rows matched: 1  Changed: 1  Warnings: 0
  6. -- 查询当前终端线程ID
  7. SELECT thread_id FROM threads WHERE processlist_id=CONNECTION_ID() \G
  8. -- thread_id: 58
  9. -- 1 row in set (0.00 sec)
  10. -- 查询当前活跃语句,验证环境
  11. SELECT sql_text FROM events_statements_current WHERE thread_id = 58 \G
  12. -- sql_text: SELECT * FROM events_statements_current WHERE thread_id = 58
  13. -- 1 row in set (0.00 sec)
复制代码
3) 启动终端2输入命令:
  1. USE PERFORMANCE_SCHEMA;
  2. -- 查询当前终端的thread_id
  3. SELECT THREAD_ID FROM THREADS WHERE PROCESS_LIST_ID=CONNECTION_ID() \G
  4. thread_id: 58
  5. 1 row in set (0.00 sec)
  6. source stmt_stack.sql
  7. +------+----------+
  8. | a    | SLEEP(a) |
  9. +------+----------+
  10. |    10|        0 |
  11. +------+----------+
  12. 1 row in set (10.01 sec)
  13. Query OK, 0 rows affected (10.01 sec)
复制代码
4) 切换终端1输入命令:
  1. USE PERFORMANCE_SCHEMA;
  2. mysql> SELECT sql_text FROM events_statements_current WHERE thread_id = 58;
  3. +--------------------+
  4. | sql_text           |
  5. +--------------------+
  6. | CALL p1(10)        |
  7. | SELECT a, SLEEP(a) |
  8. +--------------------+
  9. 2 rows in set (0.01 sec)
  10. mysql> SELECT sql_text FROM events_statements_current WHERE thread_id = 58;
  11. +-------------+
  12. | sql_text    |
  13. +-------------+
  14. | CALL p1(10) |
  15. +-------------+
  16. 1 row in set (0.00 sec)
复制代码
注意:58是查到的内部线程号
结论:

可以看到:语句以及内嵌语句都被STATEMENT STACK捕获,同一时刻,同个会话,多条语句。
STATEMENT STACK如何更新

计数器增加

pfs_get_thread_statement_locker_v2
计数器减少

pfs_end_statement_v2
限制与扩展说明


  • 默认情况下: statement_stack_max = 10
  • 当语句嵌套层级大于: statement_stack_max 的时候,嵌套的语句就不会记录了,全局变量: nested_statement_lost会被更新
  • 通过语句'show global status like "%performance_schema_nested_statement_lost%";' 可以查询丢失语句的数量

Enjoy GreatSQL
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

笑看天下无敌手

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表