基础材料:
centos7.5 mysql 5.7.24 开启GTID ROW格式
binlog对于mysql是至关重要的,binlog与undo redo一起保证了数据的完整性,用于数据恢复,崩溃恢复、任一时间点恢复、甚至是任意一条数据的恢复。所有的高可用模式也都是基于binlog进行处理的。
本文主要对row格式下binlog日志输出内容进行说明。
首先执行flush logs截断当前日志,生成新日志,便于查看。然后插入一条记录,使用mysqlbinlog命令查看binlog。
mysql> flush logs;
mysql> insert into testxxxx values (110,111,111);
[root@mysql1 ~]# mysqlbinlog --no-defaults -vv mysql-binlog.000003
# at 732
#190312 16:23:46 server id 98 end_log_pos 797 CRC32 0xba637854 GTID last_committed=2 sequence_number=3 rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= '92b47a33-db57-11e8-accf-000c2988a781:21'/*!*/;
# at 797
#190312 16:23:46 server id 98 end_log_pos 869 CRC32 0x82827bcc Query thread_id=48 exec_time=0 error_code=0
SET TIMESTAMP=1552379026/*!*/;
BEGIN
/*!*/;
# at 869
#190312 16:23:46 server id 98 end_log_pos 922 CRC32 0x28c80e4b Table_map: `test`.`testxxxx` mapped to number 185
# at 922
#190312 16:23:46 server id 98 end_log_pos 970 CRC32 0x9d58cf96 Write_rows: table id 185 flags: STMT_END_F
BINLOG '
kmyHXBNiAAAANQAAAJoDAAAAALkAAAAAAAEABHRlc3QACHRlc3R4eHh4AAMDAwMABksOyCg=
kmyHXB5iAAAAMAAAAMoDAAAAALkAAAAAAAEAAgAD//huAAAAbwAAAG8AAACWz1id
'/*!*/;
### INSERT INTO `test`.`testxxxx`
### SET
### @1=110 /* INT meta=0 nullable=0 is_null=0 */
### @2=111 /* INT meta=0 nullable=1 is_null=0 */
### @3=111 /* INT meta=0 nullable=1 is_null=0 */
# at 970
#190312 16:23:46 server id 98 end_log_pos 1001 CRC32 0xa52db5f9 Xid = 2932378
COMMIT/*!*/;
# at 1001
1、上图中有许多# at开头的行,用于标示每个事件在binlog中的偏移量,例如# at 732表示该事件在binlog的位置是732字节之后
两个# at之间标示了mysql中的一个事件,而且在事件开始时也会通过end_log_pos标示事件结束的位置
binlog中一个完整的事务对应多个事件,两个GTID last_committed=2 sequence_number=3这样的行之间标识了一个完整的事务。
2、 server id 98表示产生该事务服务器id号为98,这是在my.cnf文件中定义的,该id在集群内不能重复。一来是对事务产生的server做标识,二来是在类似双主模式下的集群环境里用于中断binlog循环复制重做的问题(log-slave-updates = 1)。
3、 CRC32用于校验binlog文件的完整性。
4、 GTID表示启动了GTID属性
5、 last_committed=2组提交标识、同一组提交的事务具备相同的last_committed值,可以在从库并行重放,以减少同步延迟。
6、 sequence_number=3,事务对应的顺序号,该值单调递增,同时也标识了同一组提交事务的顺序,在从库设置slave_preserve_commit_order=1时,依赖该值模拟主库的提交顺序,在从库提交。以达到数据落盘过程完全一致。
7、 SET @@SESSION.GTID_NEXT= '92b47a33-db57-11e8-accf-000c2988a781:21'/*!*/;标识该事务使用的GTID序列号,92b47a33-db57-11e8-accf-000c2988a781为该主机的标识。后面的数字21标识事务号,随事务的提交而依次递增。该GTID标识正常情况下与show master status或show slave status的输出部分一致。
8、 SET TIMESTAMP=1552379026/*!*/;标识了该事务产生的时间,在一些特殊情况下保证数据一致性。比如使用了now函数的sql,可能延迟了很长时间才传到备库,此时now函数取该值插入,保证了与主库执行时间的一致。
9、 begin开始执行事务
10、Table_map: `test`.`testxxxx` mapped to number 185,标识要操作哪个库的哪张表
11、Write_rows: table id 185 flags: STMT_END_F,标识该操作类型,本次是插入操作对应Write_rows事件
12、 ### INSERT INTO `test`.`testxxxx`
### SET
### @1=110 /* INT meta=0 nullable=0 is_null=0 */
### @2=111 /* INT meta=0 nullable=1 is_null=0 */
### @3=111 /* INT meta=0 nullable=1 is_null=0 */
这部分是具体的插入语句,@1=110表示在该表的第一个列插入值110,依次类推。如果此处是一个误删除操作,只要把前面的delete改为insert,再前滚这段binlog即可找回数据。由于语句执行时还有上下文关系,所以在不确定影响的情况下,不要只把SQL拿出来执行,而是前滚整个事务。
13、Xid = 2932378是保证数据完整性的一个标识,每个DML事务提交并完全写入binlog中结尾处一定会有Xid(DDL是没有的)。在redolog中也会记录该Xid值。在2PC提交机制中用此标识在redolog和binlog进行对比,崩溃时如果redolog没有commit,在redolog和binlog都有该值时,则事务重做,如果binlog没有找到该值时,则事务回滚。如果redolog也没有该值时,无需查找binlog,事务直接回滚。
14、最后由COMMIT标识提交事务