文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

MySQL binlog 中的时间戳,你明白了吗?

2024-11-29 19:49

关注

概念

binlog_format

MySQL 中 binlog 有三种模式,包括:

使用非确定性函数或语句,比如 UUID()、NOW();

操作包含触发器、存储过程或用户定义函数(UDF)。

需要注意的是可以设置的 binog 模式与事务隔离级别有关系。

If you are using InnoDB tables and the transaction isolation level is READ COMMITTED or READ UNCOMMITTED, only row-based logging can be used.

其中:

参考文章 为什么 MySQL 事务默认隔离级别是可重复读?,其中假设两个事务的执行顺序见下表。

时间

事务 A

事务 B

1

begin;

begin;

2

delete from A where a < 10;


3


insert into A values(5);

4


commit;

5

commit;


binlog 中的记录顺序如下所示。

图片

显然,事务的执行顺序与提交顺序不同,而 binlog 中的记录顺序与事务的提交顺序相同,因此导致主从事务的执行顺序不同,从而出现数据不一致。

Event

本节参考《深入理解 MySQL 主从原理》。

每个事务的 binlog 由多个 Event 组成,每个 Event 的主要结构包括:

timestamp,保存语句开始执行的时间,正是本文重点关注的字段;

type_code,保存 Event 的类型;

server_id,保存生成 Event 的数据库的 server_id;

event_len,保存整个 Event 的长度;

end_log_p,保存下一个 Event 的开始位置;

如下所示,是语句模式下一段 binlog Event,其中红框中都是 Event header。

图片

常见的 Event 类型按照写入文件的顺序包括:

测试

测试环境

数据库版本:5.7.24

事务隔离级别:RR

开始测试前指定提示符 prompt,从而将命令行的当前时间显示在前面。

/export/servers/mysql/bin/mysql -uadmin -p3341 -h 127.0.0.1 -P 3341 -D test_zk --prompt='\r:\m:\s> '

注意显示的时间与命令开始执行的时间会有偏差,原因是输入命令需要时间,而显示的时间是输入命令的开始时间。

下面分别测试行模式与语句模式下隐式事务与显式事务写入 binlog 的区别。

行模式

隐式事务

08:27:31> update t3_bak set create_time=now() where id<1000000;
Query OK, 999989 rows affected (8.81 sec)
Rows matched: 999989  Changed: 999989  Warnings: 0

查看 binlog;

# at 194
#240813  8:27:32 server id 3341  end_log_pos 259 CRC32 0x8f3d5b01       GTID    last_committed=0        sequence_number=1       rbr_notallow=yes
;
SET @@SESSION.GTID_NEXT= 'd16716c7-c94e-11ed-a186-fa163e19c3b7:67636';
# at 259
#240813  8:27:32 server id 3341  end_log_pos 342 CRC32 0x83532332       Query   thread_id=1250  exec_time=0     error_code=0
SET TIMESTAMP=1723508852;
BEGIN
;
# at 342
#240813  8:27:32 server id 3341  end_log_pos 418 CRC32 0xde6a90cd       Rows_query
# update t3_bak set create_time=now() where id<1000000
# at 418
#240813  8:27:32 server id 3341  end_log_pos 477 CRC32 0x3c9742c6       Table_map: `test_zk`.`t3_bak` mapped to number 2270
# at 477
#240813  8:27:32 server id 3341  end_log_pos 8649 CRC32 0x0a5f2233      Update_rows: table id 2270
# at 8649
#240813  8:27:32 server id 3341  end_log_pos 16825 CRC32 0x4a036014     Update_rows: table id 2270
...
# at 44194605
#240813  8:27:32 server id 3341  end_log_pos 44194636 CRC32 0xd524e4c2  Xid = 1520760
COMMIT;

其中:

显式事务

08:32:05> begin;
Query OK, 0 rows affected (0.00 sec)

08:32:15> update t3_bak set create_time=now() where id<1000000;
Query OK, 999989 rows affected (8.68 sec)
Rows matched: 999989  Changed: 999989  Warnings: 0

08:32:45> commit;
Query OK, 0 rows affected (0.21 sec)

binlog:

# at 194
#240813  8:32:46 server id 3341  end_log_pos 259 CRC32 0xd3661504       GTID    last_committed=0        sequence_number=1       rbr_notallow=yes
;
SET @@SESSION.GTID_NEXT= 'd16716c7-c94e-11ed-a186-fa163e19c3b7:67637';
# at 259
#240813  8:32:16 server id 3341  end_log_pos 342 CRC32 0x99dba315       Query   thread_id=1250  exec_time=0     error_code=0
SET TIMESTAMP=1723509136;
BEGIN
;
# at 342
#240813  8:32:16 server id 3341  end_log_pos 418 CRC32 0x9138a9a5       Rows_query
# update t3_bak set create_time=now() where id<1000000
...
# at 44194605
#240813  8:32:46 server id 3341  end_log_pos 44194636 CRC32 0x892dfbf1  Xid = 1520766
COMMIT;

其中:

分析

到这里,可以提出以下三个问题:

下面分析原因。

首先是第一个问题,为什么隐式事务中所有 event timestamp 等于 update 的开始时间,包括 XID_EVENT。

原因是每条命令执行前获取时间戳,通过函数 thd->set_time() 获取,而这条语句生成的多个 event 的时间戳从语句继承过来。

隐式事务中必然仅执行一条 SQL,因此所有 event timestamp 等于 update 的开始时间。

然后是第二个问题,为什么显式事务中 event timestamp 乱序。

8:32:46 GTID
8:32:16 Query
8:32:16 Rows_query
8:32:46 XID

其中:

最后是第三个问题,为什么隐式事务与显式事务中 query event 均显示 exec_time=0。

原因是:

因此,对于行模式:

可以得出以下两点结论:

语句模式

修改 binlog 模式;

set session binlog_format='statement';

隐式事务

18:12:31> update t3_bak set create_time=now() where id<1000000;
Query OK, 999989 rows affected (8.19 sec)
Rows matched: 999989  Changed: 999989  Warnings: 0

binlog;

# at 194
#240816 18:12:32 server id 3341  end_log_pos 259 CRC32 0x47293428       GTID    last_committed=0        sequence_number=1       rbr_notallow=no
SET @@SESSION.GTID_NEXT= 'd16716c7-c94e-11ed-a186-fa163e19c3b7:67648';
# at 259
#240816 18:12:32 server id 3341  end_log_pos 352 CRC32 0xf5dd67f7       Query   thread_id=1261  exec_time=8     error_code=0
BEGIN
;
# at 352
#240816 18:12:32 server id 3341  end_log_pos 492 CRC32 0xc5d67750       Query   thread_id=1261  exec_time=8     error_code=0
use `test_zk`;
SET TIMESTAMP=1723803152;
update t3_bak set create_time=now() where id<1000000
;
# at 492
#240816 18:12:32 server id 3341  end_log_pos 523 CRC32 0xe90b07a7       Xid = 1521788
COMMIT;

其中:

查看 event,可以更清楚的看到事务的全部 event。

18:25:39> show binlog events in 'mysql-bin.000080';
+------------------+-----+----------------+-----------+-------------+-----------------------------------------------------------------------+
| Log_name         | Pos | Event_type     | Server_id | End_log_pos | Info                                                                  |
+------------------+-----+----------------+-----------+-------------+-----------------------------------------------------------------------+
| mysql-bin.000080 |   4 | Format_desc    |      3341 |         123 | Server ver: 5.7.24-log, Binlog ver: 4                                 |
| mysql-bin.000080 | 123 | Previous_gtids |      3341 |         194 | d16716c7-c94e-11ed-a186-fa163e19c3b7:1-67647                          |
| mysql-bin.000080 | 194 | Gtid           |      3341 |         259 | SET @@SESSION.GTID_NEXT= 'd16716c7-c94e-11ed-a186-fa163e19c3b7:67648' |
| mysql-bin.000080 | 259 | Query          |      3341 |         352 | BEGIN                                                                 |
| mysql-bin.000080 | 352 | Query          |      3341 |         492 | use `test_zk`; update t3_bak set create_time=now() where id<1000000   |
| mysql-bin.000080 | 492 | Xid            |      3341 |         523 | COMMIT                                               |
+------------------+-----+----------------+-----------+-------------+-----------------------------------------------------------------------+
6 rows in set (0.00 sec)

其中:

显式事务

19:16:49> begin;
Query OK, 0 rows affected (0.00 sec)

19:16:54> update t3_bak set create_time=now() where id<1000000;
Query OK, 999989 rows affected (8.47 sec)
Rows matched: 999989  Changed: 999989  Warnings: 0

19:17:19> commit;
Query OK, 0 rows affected (0.01 sec)

binlog;

# at 194
#240816 19:17:19 server id 3341  end_log_pos 259 CRC32 0x364ff2e2       GTID    last_committed=0        sequence_number=1       rbr_notallow=no
SET @@SESSION.GTID_NEXT= 'd16716c7-c94e-11ed-a186-fa163e19c3b7:67649';
# at 259
#240816 19:16:54 server id 3341  end_log_pos 352 CRC32 0x368c08f4       Query   thread_id=1261  exec_time=8     error_code=0
BEGIN
;
# at 352
#240816 19:16:54 server id 3341  end_log_pos 492 CRC32 0x0450bba8       Query   thread_id=1261  exec_time=8     error_code=0
use `test_zk`;
SET TIMESTAMP=1723807014;
update t3_bak set create_time=now() where id<1000000
;
# at 492
#240816 19:17:19 server id 3341  end_log_pos 523 CRC32 0xf75171f9       Xid = 1521794
COMMIT;

其中:

对比

类型

exec_time

所有 event timestamp 相同

行模式 + 隐式事务

通常等于 0


行模式 + 显式事务

通常等于 0


语句模式 + 隐式事务

等于事务中第一条 SQL 的执行用时


语句模式 + 显式事务

等于事务中第一条 SQL 的执行用时


其中:

结论

本文主要测试并介绍 binlog event header 的 timestamp 字段与 QUERY_EVENT 中的 exec_time 字段。

binlog event header 的 timestamp 字段中保存语句开始执行的时间,具体取值与是否使用显式事务有关:

QUERY_EVENT 中的 exec_time 字段中保存更改第一条数据的执行用时,具体取值与 binlog 的模式有关:

因此,对于行模式:

此外可以发现 timestamp 对于大事务与长事务主从延迟的影响:

具体将在下一篇文章中讲解。

来源:丹柿小院内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯