zoukankan      html  css  js  c++  java
  • binlog记录SQL执行时间吗,准不准,时间是否包含锁等待时间

    讨论:binlog记录SQL执行时间吗,准不准,时间是否包含锁等待时间

    MySQL版本号:

    Server version: 5.7.29-log MySQL Community Server (GPL)

    测试环境如下:

    mysql> drop table t1;
    Query OK, 0 rows affected (0.02 sec)
    
    mysql> create table t1(id int primary key auto_increment,name varchar(200));
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> insert into t1 select null,repeat('a',2000);
    Query OK, 1 row affected, 1 warning (0.00 sec)
    Records: 1  Duplicates: 0  Warnings: 1
    
    mysql> insert into t1 select null,repeat('a',2000) from t1;
    Query OK, 1 row affected, 1 warning (0.01 sec)
    Records: 1  Duplicates: 0  Warnings: 1
    ....
    插入100W+条数据,让这个表大一些

    找一个DEMO,简单分析下binlog文件,binlog文件本质上是由一个个event组成的,

    [root@host101 data]# 
    [root@host101 data]# mysqlbinlog -vv --base64-output=decode-rows mysql-bin.000059
    /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
    /*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
    DELIMITER /*!*/;
    # at 4
    #201107 16:47:03 server id 1  end_log_pos 123 CRC32 0x17ba10af     Start: binlog v 4, server v 5.7.29-log created 201107 16:47:03   ---binlog文件中的第一个event,FORMAT_DESCRIPTION_EVENT,生成时机是binlog文件切换时
    # Warning: this binlog is either in use or was not closed properly.
    # at 123
    #201107 16:47:03 server id 1  end_log_pos 234 CRC32 0x26a0a898     Previous-GTIDs
    # 9fef2262-97b1-11ea-92b5-000c29cd3ff3:1-1583,
    # adc4403d-97b2-11ea-b803-000c298076e0:1-104                                               ----binlog文件中第二个event,PREVIOUS_GTIDS_LOG_EVENT,用于描述前面所有binary log中包含的GTID SET
    # at 234
    #201107 16:47:05 server id 1  end_log_pos 299 CRC32 0x79365d3f     GTID    last_committed=0    sequence_number=1    rbr_only=yes   
    /*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
    SET @@SESSION.GTID_NEXT= '9fef2262-97b1-11ea-92b5-000c29cd3ff3:1584'/*!*/;                 ----binlog文件中第三个event,GTID_LOG_EVENT,用于描述GTID的详细信息,是否为行行为,逻辑时钟详细信息,即last_committed和sequence_number        
    # at 299
    #201107 16:47:05 server id 1  end_log_pos 377 CRC32 0x44b83854     Query    thread_id=315    exec_time=0    error_code=0   ****---QUERY_EVENT,讨论重点是exec_time,是否是准确时间。****
    SET TIMESTAMP=1604738825/*!*/;
    SET @@session.pseudo_thread_id=315/*!*/;
    SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
    SET @@session.sql_mode=0/*!*/;
    SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=2/*!*/;
    /*!C utf8 *//*!*/;
    SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=33/*!*/;
    SET @@session.lc_time_names=0/*!*/;
    SET @@session.collation_database=DEFAULT/*!*/;
    BEGIN
    /*!*/;
    # at 377
    #201107 16:47:05 server id 1  end_log_pos 423 CRC32 0x9bf22279     Table_map: `ceshi`.`t1` mapped to number 108     ----MAP_EVENT,行模式特有的,用做table_id和实际访问表的映射等。
    # at 423
    #201107 16:47:05 server id 1  end_log_pos 463 CRC32 0xc3e374f6     Write_rows: table id 108 flags: STMT_END_F       ---WRITE_ROWS_EVENT,是insert语句生成的event.用于记录insert语句的ager_image实际数据。
    ### INSERT INTO `ceshi`.`t1`
    ### SET
    ###   @1=1 /* INT meta=0 nullable=1 is_null=0 */
    # at 463
    #201107 16:47:05 server id 1  end_log_pos 494 CRC32 0x86bb8b11     Xid = 14938
    COMMIT/*!*/;
    SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
    DELIMITER ;
    # End of log file
    /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
    /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
    ****---QUERY_EVENT,讨论重点是exec_time,是否是准确时间。****
    exec_time是在QUERY_EVENT中记录的,
    根据之前学习【深入理解MySQL主从32讲】,结论是:
    DML:执行时间记录的是第一条数据更改后的时间,而不是真正本条DML语句执行的时间(一个DML语句可能修改很多条记录),往往这个时间非常短短,不能正确的表示DML语句执行的时间。语句部分记录的是BEGIN。
    DDL:执行时间是实际语句的执行时间,部分语句记录的是实际的语句。

    1、验证下DML时间统计的结论,命令执行时间10.30秒,
    binlog中解析到的exec_time=0 ,之前的结成立,exec_time记录是修改第一条记录的时间,修改一条记录的时间是很快的。
    mysql> flush binary logs;
    Query OK, 0 rows affected (0.02 sec)
    
    mysql> update t1 set name=repeat('c',2000);
    Query OK, 131072 rows affected, 65535 warnings (10.30 sec)
    Rows matched: 131072  Changed: 131072  Warnings: 131072

    binlog

    #201107 17:21:09 server id 1  end_log_pos 377 CRC32 0x6f3d46e9  Query   thread_id=315   exec_time=0     error_code=0
    SET TIMESTAMP=1604740869/*!*/;
    SET @@session.pseudo_thread_id=315/*!*/;
    SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
    SET @@session.sql_mode=0/*!*/;
    SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=2/*!*/;
    /*!C utf8 *//*!*/;
    SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=33/*!*/;
    SET @@session.lc_time_names=0/*!*/;
    SET @@session.collation_database=DEFAULT/*!*/;
    BEGIN
    /*!*/;
    # at 377
    #201107 17:21:09 server id 1  end_log_pos 426 CRC32 0x139eedd0  Table_map: `ceshi`.`t1` mapped to number 119
    # at 426
    #201107 17:21:09 server id 1  end_log_pos 8328 CRC32 0x07294435         Update_rows: table id 119
    # at 8328
    #201107 17:21:09 server id 1  end_log_pos 16230 CRC32 0x3fca917d        Update_rows: table id 119
    # at 16230
    #201107 17:21:09 server id 1  end_log_pos 24132 CRC32 0xd40fb927        Update_rows: table id 119
    # at 24132
    ...........

    2、验证下DDL命令时间统计,命令执行时间1.57秒,

    binlog中exec_time=2 ,应该是把时间四舍五入了,结论成立。

    mysql> flush binary logs;
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> alter table t1 add age int;
    Query OK, 0 rows affected (1.57 sec)
    Records: 0  Duplicates: 0  Warnings: 0

    binlog

    #201107 17:24:22 server id 1  end_log_pos 406 CRC32 0x26d06826  Query   thread_id=315   exec_time=2     error_code=0
    use `ceshi`/*!*/;
    SET TIMESTAMP=1604741062/*!*/;
    SET @@session.pseudo_thread_id=315/*!*/;
    SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
    SET @@session.sql_mode=0/*!*/;
    SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=2/*!*/;
    /*!C utf8 *//*!*/;
    SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=33/*!*/;
    SET @@session.lc_time_names=0/*!*/;
    SET @@session.collation_database=DEFAULT/*!*/;
    alter table t1 add age int
    /*!*/;

    3、之前的实验都是在没有锁发生的情况测试的,如果遇到Innodb行锁,或MDL锁,不知exec_time是否会包含这个时间,测试如下,先删掉之前添回执age列,重新做测试 。

      3.1故意让update命令产生行锁等待,看下binlog的exec_time时间。

    t1时间

    session1:

    mysql> begin;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> select * from t1 where id=1 for update;
    +----+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | id | name                                                                                                                                                                                                     |
    +----+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    |  1 | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc |
    +----+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    1 row in set (0.01 sec)

    t2时间

    sessino2:

    mysql> use ceshi;
    Reading table information for completion of table and column names
    You can turn off this feature to get a quicker startup with -A
    
    Database changed
    mysql> update t1 set name=repeat('d',2000);      ----处于锁等待状态

    过一会儿(大约10秒钟左右,心中默数的),

    t3时间,session1释放掉锁

    mysql> select * from t1 where id=1 for update;
    +----+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | id | name                                                                                                                                                                                                     |
    +----+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    |  1 | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc |
    +----+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    1 row in set (0.01 sec)
    
    mysql> rollback;
    Query OK, 0 rows affected (0.01 sec)

    t4时间,session2持有锁开始更新记录,SQL显示执行了22.11秒(其中包括锁等待时间)

    mysql> update t1 set name=repeat('d',2000);
    Query OK, 131072 rows affected, 65535 warnings (22.11 sec)
    Rows matched: 131072  Changed: 131072  Warnings: 131072

    binlog

    #201107 21:37:03 server id 1  end_log_pos 377 CRC32 0x01b20225  Query   thread_id=607   exec_time=13    error_code=0
    SET TIMESTAMP=1604756223/*!*/;
    SET @@session.pseudo_thread_id=607/*!*/;
    SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
    SET @@session.sql_mode=0/*!*/;
    SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=2/*!*/;
    /*!C utf8 *//*!*/;
    SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=33/*!*/;
    SET @@session.lc_time_names=0/*!*/;
    SET @@session.collation_database=DEFAULT/*!*/;
    BEGIN
    /*!*/;
    # at 377
    #201107 21:37:03 server id 1  end_log_pos 426 CRC32 0x87b8f0c1  Table_map: `ceshi`.`t1` mapped to number 121
    # at 426
    #201107 21:37:03 server id 1  end_log_pos 8328 CRC32 0xd5053a6d         Update_rows: table id 121
    # at 8328
    #201107 21:37:03 server id 1  end_log_pos 16230 CRC32 0xede6ef25        Update_rows: table id 121
    # at 16230
    ........

      3.1小结:binlog中exec_time记录行锁等待的时间,实际锁等待时间应该就是13秒,但仍然不能代表update 语句实际执行时间, 因为它实际计算的是update语句更新第一条记录需要的时间。

      3.2故意让update命令产生MDL锁等待,看下binlog的exec_time时间。

    t1时间

    session1:锁定t1表

    mysql> flush table t1 with read lock;
    Query OK, 0 rows affected (0.01 sec)

    t2时间

    session2:做更新,处于卡住状态。

    mysql> update t1 set name=repeat('e',2000);

    执行个show processlist,确定现在是等待获取MDL锁状态 

    mysql> show processlist;
    +-----+---------+-----------------------+--------------------+------------------+-------+---------------------------------------------------------------+-------------------------------------+
    | Id  | User    | Host                  | db                 | Command          | Time  | State                                                         | Info                                |
    +-----+---------+-----------------------+--------------------+------------------+-------+---------------------------------------------------------------+-------------------------------------+
    |  12 | root    | 192.168.150.150:36454 | information_schema | Sleep            |    26 |                                                               | NULL                                |
    | 322 | root    | 192.168.150.102:56206 | NULL               | Binlog Dump GTID | 17926 | Master has sent all binlog to slave; waiting for more updates | NULL                                |
    | 323 | root    | 192.168.150.103:43044 | NULL               | Binlog Dump GTID | 17910 | Master has sent all binlog to slave; waiting for more updates | NULL                                |
    | 607 | root    | localhost             | ceshi              | Query            |     6 | Waiting for table metadata lock                               | update t1 set name=repeat('e',2000) |
    | 609 | root    | localhost             | ceshi              | Sleep            |    11 |                                                               | NULL                                |
    | 620 | monitor | 192.168.150.150:40076 | NULL               | Sleep            |     0 |                                                               | NULL                                |
    | 621 | monitor | 192.168.150.150:40078 | NULL               | Sleep            |     5 |                                                               | NULL                                |
    | 631 | root    | localhost             | NULL               | Query            |     0 | starting                                                      | show processlist                    |
    +-----+---------+-----------------------+--------------------+------------------+-------+---------------------------------------------------------------+-------------------------------------+
    8 rows in set (0.00 sec)

    t3时间

    session1:释放MDL锁

    mysql> flush table t1 with read lock;
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> unlock tables;
    Query OK, 0 rows affected (0.01 sec)

    t4时间:

    session2:执行完成了

    mysql> update t1 set name=repeat('e',2000);
    Query OK, 131072 rows affected, 65535 warnings (2 min 46.26 sec)
    Rows matched: 131072  Changed: 131072  Warnings: 131072
    
    mysql> 

    binlog

    #201107 21:46:44 server id 1  end_log_pos 54512694 CRC32 0xe9c2432b     GTID    last_committed=1        sequence_number=2       rbr_only=yes
    /*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
    SET @@SESSION.GTID_NEXT= '9fef2262-97b1-11ea-92b5-000c29cd3ff3:1615'/*!*/;
    # at 54512694
    #201107 21:46:44 server id 1  end_log_pos 54512772 CRC32 0x47413c2e     Query   thread_id=607   exec_time=157   error_code=0
    SET TIMESTAMP=1604756804/*!*/;
    BEGIN
    /*!*/;
    # at 54512772
    #201107 21:46:44 server id 1  end_log_pos 54512821 CRC32 0x7384f6e6     Table_map: `ceshi`.`t1` mapped to number 122
    # at 54512821
    #201107 21:46:44 server id 1  end_log_pos 54520723 CRC32 0x8570824e     Update_rows: table id 122
    # at 54520723
    #201107 21:46:44 server id 1  end_log_pos 54528625 CRC32 0xeb6a3741     Update_rows: table id 122

      3.2小结:binlog中exec_time记录MDL锁等待的时间,实际锁等待时间应该就是157秒,但仍然不能代表update 语句实际执行时间, 因为它实际计算的是update语句更新第一条记录需要的时间。

      通过个结论,我们可以后期通过exec_time内容分析当时的DML操作有没有遇到行锁或MDL锁。

    4.1

    DDL命令不会遇到行锁,但会遇到MDL锁,测试DDL命令在遇到MDL锁的时候,binlog中exec_time是否有记录。

    t1时间

    session1:

    mysql> flush table t1 with read lock;
    Query OK, 0 rows affected (0.00 sec)

    t2时间

    session2:

    mysql> alter table t1 add age int;

    执行个show processlist,确定现在是等待获取MDL锁状态 

    mysql> show processlist;
    +-----+---------+-----------------------+--------------------+------------------+-------+---------------------------------------------------------------+----------------------------+
    | Id  | User    | Host                  | db                 | Command          | Time  | State                                                         | Info                       |
    +-----+---------+-----------------------+--------------------+------------------+-------+---------------------------------------------------------------+----------------------------+
    |  12 | root    | 192.168.150.150:36454 | information_schema | Sleep            |    53 |                                                               | NULL                       |
    | 322 | root    | 192.168.150.102:56206 | NULL               | Binlog Dump GTID | 18914 | Master has sent all binlog to slave; waiting for more updates | NULL                       |
    | 323 | root    | 192.168.150.103:43044 | NULL               | Binlog Dump GTID | 18898 | Master has sent all binlog to slave; waiting for more updates | NULL                       |
    | 607 | root    | localhost             | ceshi              | Query            |    83 | Waiting for table metadata lock                               | alter table t1 add age int |
    | 609 | root    | localhost             | ceshi              | Sleep            |    94 |                                                               | NULL                       |
    | 637 | monitor | 192.168.150.150:40180 | NULL               | Sleep            |     1 |                                                               | NULL                       |
    | 643 | root    | localhost             | NULL               | Query            |     0 | starting                                                      | show processlist           |
    +-----+---------+-----------------------+--------------------+------------------+-------+---------------------------------------------------------------+----------------------------+
    7 rows in set (0.00 sec)

    t3时间

    session1:释放掉持有的MDL锁

    mysql> flush table t1 with read lock;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> unlock tables;
    Query OK, 0 rows affected (0.00 sec)

    t4时间

    session2:执行了124.83秒

    mysql> alter table t1 add age int;
    Query OK, 0 rows affected (2 min 4.83 sec)
    Records: 0  Duplicates: 0  Warnings: 0

    binlog

    #201107 22:01:55 server id 1  end_log_pos 406 CRC32 0xa73826c4  Query   thread_id=607   exec_time=125   error_code=0
    use `ceshi`/*!*/;
    SET TIMESTAMP=1604757715/*!*/;
    SET @@session.pseudo_thread_id=607/*!*/;
    SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
    SET @@session.sql_mode=0/*!*/;
    SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=2/*!*/;
    /*!C utf8 *//*!*/;
    SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=33/*!*/;
    SET @@session.lc_time_names=0/*!*/;
    SET @@session.collation_database=DEFAULT/*!*/;
    alter table t1 add age int
    /*!*/;

       3.2总结:binlog中exec_time会计算DDL命令等待MDL锁的时间。

    总结:

    1、DDL命令和DML命令,在记binlog时exec_time都会算上锁等待的时间(包括行锁和MDL锁)。

    2、DML操作的exec_time可以倒推出当时执行命令的时候有没有遇到行锁或MDL锁。

    3、由于DDL操作记录的是命令执行所有时间,无法倒推出执行时有没有遇到MDL锁,只能根据经验看,这个命令执行耗时是否不正常,如果不正常,可以怀疑执行时遇到了MDL锁。

  • 相关阅读:
    拾回被剥削的自由,未来实实在在的弹性工作一定成为主流
    探索RequestBody报com.alibaba.fastjson.JSONObject cannot be cast to xxx
    CSM与UEFI
    JS使用onscroll、scrollTop实现图片懒加载
    点击button后刷新了页面
    jQuery中prop和attr区别
    encodeURI、encodeURIComponent
    局中人
    年轻人能为世界做些什么
    JavaWeb中的资源映射
  • 原文地址:https://www.cnblogs.com/nanxiang/p/13062989.html
Copyright © 2011-2022 走看看