• 有趣的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;
    //...
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    其中:

    • 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);
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    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)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    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)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    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)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    注意: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

    6440

  • 相关阅读:
    问题:在 main 方法中使用 httpclient 时,idea 控制台会疯狂打印 DEBUG org.apache.http.wire 的日志
    kubectl系列(四)-kubectl apply
    Electron[3] 基础配置准备和Electron入门案例
    一、MRP计算前的一些准备知识
    C# 委托和事件
    【MM小贴士】关于SAP系统中关税的处理方式
    如何记录分析你的炼丹流程—可视化神器Wandb使用笔记【1】
    线性代数学习笔记5-1:正交的向量/空间、正交补(行空间和零空间正交)
    虚拟列表的原理
    第8章 虚拟现实技术的相关软件
  • 原文地址:https://blog.csdn.net/GreatSQL2021/article/details/127882816