有趣的statement stack
引子
在使用events_statements_current的过程中发现,同一线程在同一时刻,可能有多条记录,与直观感觉不太一样,于是跟踪了一下内部实现,有了本文。
STATEMENT STACK的定义
STATEMENT STACK 是events_statements_current表被后用于存储当前会话执行语句堆栈的数据结构。
在MySQL8中,相关定义如下:
/** Max size of the statements stack. */ uint statement_stack_max; /** nested statement lost */ uint nested_statement_lost; struct PFS_ALIGNED PFS_thread : PFS_connection_slice { //... /** Size of @c m_events_statements_stack. */ uint m_events_statements_count; PFS_events_statements *m_statement_stack; //... }
其中:
- m_statement_stack 语句堆栈
- m_events_statements_count 语句堆栈栈顶指针
- statement_stack_max 存储允许存储的最大语句数量
- nested_statement_lost 存储丢失的语句数量
STATEMENT STACK相关小实验
1) 创建测试存储过程
存储过程的功能主要是:人为等待10秒左右
-- 保存为:stat_stack.sql USE d1; set sql_mode=oracle; set global log_bin_trust_function_creators = 1; DELIMITER $$ CREATE OR REPLACE PROCEDURE p1(a INT DEFAULT 1) AS BEGIN SELECT a, SLEEP(a); END$$ CALL p1(10);
2) 启动终端1输入命令:
USE PERFORMANCE_SCHEMA; -- 确认采集打开 UPDATE setup_consumers SET ENABLED='YES' WHERE name = 'events_statements_current'; -- Query OK, 0 rows affected (0.00 sec) -- Rows matched: 1 Changed: 1 Warnings: 0 -- 查询当前终端线程ID SELECT thread_id FROM threads WHERE processlist_id=CONNECTION_ID() \G -- thread_id: 58 -- 1 row in set (0.00 sec) -- 查询当前活跃语句,验证环境 SELECT sql_text FROM events_statements_current WHERE thread_id = 58 \G -- sql_text: SELECT * FROM events_statements_current WHERE thread_id = 58 -- 1 row in set (0.00 sec)
3) 启动终端2输入命令:
USE PERFORMANCE_SCHEMA; -- 查询当前终端的thread_id SELECT THREAD_ID FROM THREADS WHERE PROCESS_LIST_ID=CONNECTION_ID() \G thread_id: 58 1 row in set (0.00 sec) source stmt_stack.sql +------+----------+ | a | SLEEP(a) | +------+----------+ | 10| 0 | +------+----------+ 1 row in set (10.01 sec) Query OK, 0 rows affected (10.01 sec)
4) 切换终端1输入命令:
USE PERFORMANCE_SCHEMA; mysql> SELECT sql_text FROM events_statements_current WHERE thread_id = 58; +--------------------+ | sql_text | +--------------------+ | CALL p1(10) | | SELECT a, SLEEP(a) | +--------------------+ 2 rows in set (0.01 sec) mysql> SELECT sql_text FROM events_statements_current WHERE thread_id = 58; +-------------+ | sql_text | +-------------+ | CALL p1(10) | +-------------+ 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 😃
关于 GreatSQL
GreatSQL是由万里数据库维护的MySQL分支,专注于提升MGR可靠性及性能,支持InnoDB并行查询特性,是适用于金融级应用的MySQL分支版本。
相关链接: GreatSQL社区 Gitee GitHub Bilibili
GreatSQL社区:
捉虫活动详情:https://greatsql.cn/thread-97-1-1.html
社区博客有奖征稿详情:https://greatsql.cn/thread-100-1-1.html
技术交流群:
微信:扫码添加
GreatSQL社区助手
微信好友,发送验证信息加群
。
)
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库