美文网首页
慢查询中关于MDL LOCK记录的变化

慢查询中关于MDL LOCK记录的变化

作者: 重庆八怪 | 来源:发表于2024-10-07 21:36 被阅读0次

    首先,这里不考虑innodb行锁,仅仅考虑MDL LOCK和DML/select 语句。我们知道到了8.0.28(包含)以后,记录慢查询的标准有变化,主要依赖的实际执行时间,而不是以前去掉了锁的时间(包含MDL LOCK和行锁)作为判定标准,具体参考,
    https://www.jianshu.com/p/27547eb97d6a

    以前通常通过lock_time来判断是否可能出现过innodb行锁堵塞和MDL LOCK堵塞,但是后来发现在8.0.28(包含)以后lock_time记录的时间变化了,通常并不包含innodb表的MDL LOCK时间,可以做测试如下,首先设置参数, set global long_query_time = 0,位了记录全部的满查询。

    使用如下步骤,我们观察最后selet 语句的lock_time时间是否包含了MDL LOCK时间

    步骤 session1 session2 session3
    1. begin;select * from t1
    2. alter table t1 add ic int;
    3. select * from t1; (我们主要观察本语句lock time记录时间的不同)
    4. commit;

    其中第2步开始 session2和session3 因为mdl lock的原因不能获取到锁,直到第4步commit解锁。

    8.0.28及之后的记录

    # Time: 2024-10-08T17:40:48.426038+08:00
    # User@Host: root[root] @ localhost []  Id:    29
    # Query_time: 13.729913  Lock_time: 0.000019 Rows_sent: 2  Rows_examined: 2
    SET timestamp=1728380434;
    select * from t1;
    

    注意这里的lock_time,几乎没有什么值,而这两个语句很明显的是等待在MDL LOCK下面,而lock_time几乎为0,因此在8.0.28及之后即便Lock_time为0不能说明语句没有遇到MDL LOCK

    8.0.28及之前的记录,这里使用8.0.23

    注意这里一定要将long_query_time 设置为0,否则如果主要等待在MDL LOCK上,去掉这部分时间后可能实际执行时间已经很短了,因此如果不设置long_query_time 为0不会记录任何慢查询。

    # Time: 2024-10-08T18:02:47.417947+08:00
    # User@Host: root[root] @ localhost []  Id:    19
    # Query_time: 16.397964  Lock_time: 16.396849 Rows_sent: 1  Rows_examined: 1
    SET timestamp=1728381751;
    select * from t1;
    

    这里我们能看到Lock_time实际上还是至少是包含了mdl lock的时间的。

    大体原因

    对于一般的DML和SELCET语句来讲,8.0.28之前的版本记录的lock _time的时候语句当跑到mysql_lock_tables函数的时候计算一次时间,这个时间实际上包含了MDL LOCK的时间,但是到了8.0.28(包含)以后这里发生了一些变化,仅仅记录了mysql_lock_tables函数里面消耗的时间,可以在函数找到如下几句,

    ulonglong lock_start_usec = my_micro_time(); //仅仅是这一段 记录到了lock time
    ulonglong lock_end_usec = my_micro_time(); //结束
    thd->inc_lock_usec(lock_end_usec - lock_start_usec);//计算
    

    但是innodb表的MDL LOCK堵塞并不包含在这个函数中,因此8.0.28及过后的MDL LOCK堵塞就不会记录了。
    但是myisam的表锁是包含在其中,当我们使用myisam 测试表锁的时候会发现表锁的时间记录在里面,如下是8.0.36的测试,


    image.png

    myisam表记录的慢查询如下,

    # Time: 2024-10-08T18:27:27.772193+08:00
    # User@Host: root[root] @ localhost []  Id:    28
    # Query_time: 67.663484  Lock_time: 67.636786 Rows_sent: 0  Rows_examined: 4
    SET timestamp=1728383180;
    delete from testmyisam;
    

    可以看到即便是8036,myisam的表锁也包含在Lock_time中。

    总结

    • 对于DML/SELECT 语句来讲,在8.0.28(包含)以后慢查询中的lock_time通常不包含MDL LOCK堵塞的时间,因此即便lock_time为0不能说明没有遇到MDL LOCK堵塞,但是lock_time包含了innodb 行锁堵塞的时间。
    • 对于DML/SELECT 语句来讲,在8.0.28之前的慢查询中的lock_time通常包含了MDL LOCK堵塞的时间,且包含innodb 行锁堵塞的时间。
    • 对于myisam的表锁堵塞始终包含在Lock_time中。

    相关文章

      网友评论

          本文标题:慢查询中关于MDL LOCK记录的变化

          本文链接:https://www.haomeiwen.com/subject/nndvrjtx.html