引子 在使用events_statements_current的過程中發現,同一線程在同一時刻,可能有多條記錄,與直觀感覺不太一樣,於是跟蹤了一下內部實現,有了本文。 STATEMENT STACK的定義 STATEMENT STACK 是events_statements_current表被後用於 ...
引子
在使用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