有趣的statement stack
引子
在使用events_statements_current的過程中發(fā)現(xiàn),同一線程在同一時刻,可能有多條記錄,與直觀感覺不太一樣,于是跟蹤了一下內(nèi)部實現(xiàn),有了本文。
STATEMENT STACK的定義
STATEMENT STACK 是events_statements_current表被后用于存儲當(dāng)前會話執(zhí)行語句堆棧的數(shù)據(jù)結(jié)構(gòu)。
在MySQL8中,相關(guān)定義如下:
/** 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 存儲允許存儲的最大語句數(shù)量
nested_statement_lost 存儲丟失的語句數(shù)量
STATEMENT STACK相關(guān)小實驗
1) 創(chuàng)建測試存儲過程
存儲過程的功能主要是:人為等待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;
-- 確認(rèn)采集打開
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
-- 查詢當(dāng)前終端線程ID
SELECT thread_id FROM threads WHERE processlist_id=CONNECTION_ID() \G
-- thread_id: 58
-- 1 row in set (0.00 sec)
-- 查詢當(dāng)前活躍語句,驗證環(huán)境
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;
-- 查詢當(dāng)前終端的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是查到的內(nèi)部線程號
結(jié)論:
可以看到:語句以及內(nèi)嵌語句都被STATEMENT STACK捕獲,同一時刻,同個會話,多條語句。
STATEMENT STACK如何更新
計數(shù)器增加
pfs_get_thread_statement_locker_v2
計數(shù)器減少
pfs_end_statement_v2
限制與擴展說明
默認(rèn)情況下: statement_stack_max = 10
當(dāng)語句嵌套層級大于: statement_stack_max 的時候,嵌套的語句就不會記錄了,全局變量: nested_statement_lost會被更新
通過語句'show global status like "%performance_schema_nested_statement_lost%";' 可以查詢丟失語句的數(shù)量
Enjoy GreatSQL ??
關(guān)于 GreatSQL
GreatSQL是由萬里數(shù)據(jù)庫維護的MySQL分支,專注于提升MGR可靠性及性能,支持InnoDB并行查詢特性,是適用于金融級應(yīng)用的MySQL分支版本。
相關(guān)鏈接:?GreatSQL社區(qū)?Gitee?GitHub?Bilibili
GreatSQL社區(qū):
捉蟲活動詳情:https://greatsql.cn/thread-97-1-1.html
社區(qū)博客有獎?wù)鞲逶斍椋篽ttps://greatsql.cn/thread-100-1-1.html
