MySQL binlog中的事件类型

MysqL binlog记录的所有操作实际上都有对应的事件类型的,譬如STATEMENT格式中的DML操作对应的是QUERY_EVENT类型,ROW格式下的DML操作对应的是ROWS_EVENT类型。

首先,看看源码中定义的事件类型

源码位置:MysqL-5.7.14/libbinlogevents/include/binlog_event.h

enum Log_event_type
{
  /**
    Every time you update this enum (when you add a type),you have to
    fix Format_description_event::Format_description_event().
  */
  UNKNowN_EVENT= 0,START_EVENT_V3= 1234tvar_EVENT= 567891011*
    NEW_LOAD_EVENT is like LOAD_EVENT except that it has a longer
    sql_ex,allowing multibyte TERMINATED BY etc; both types share the
    same class (Load_event)
  
  NEW_LOAD_EVENT= 1213141516171819*
    The PRE_GA event numbers were used for 5.1.0 to 5.1.15 and are
    therefore obsolete.
   
  PRE_GA_WRITE_ROWS_EVENT = 202122*
    The V1 event numbers are used from 5.1.16 until MysqL-trunk-xx
  
  WRITE_ROWS_EVENT_V1 = 232425*
    Something out of the ordinary happened on the master
   
  INCIDENT_EVENT= 26*
    Heartbeat event to be send by master at its idle time
    to ensure master's online status to slave
  
  HEARTBEAT_LOG_EVENT= 27*
    In some situations,it is necessary to send over ignorable
    data to the slave: data that a slave can handle in case there
    is code for handling it,but which can be ignored if it is not
    recognized.
  
  IGnorABLE_LOG_EVENT= 2829* Version 2 of the Row events 
  WRITE_ROWS_EVENT = 3031323334IoUS_GTIDS_LOG_EVENT= 353637 Prepared XA transaction terminal event similar to Xid 
  XA_PREPARE_LOG_EVENT= 38*
    Add new events here - right above this comment!
    Existing events (except ENUM_END_EVENT) should never change their numbers
  
  ENUM_END_EVENT  end marker 
};

实际上还是蛮多的,下面就挑几个重点的说一下

 

QUERY_EVENT

QUERY_EVENT以文本的形式来记录事务的操作。

QUERY_EVENT类型的事件通常在以下几种情况下使用:

1. 事务开始时,执行的BEGIN操作。

2. STATEMENT格式中的DML操作

3. ROW格式中的DDL操作

譬如:

MysqL> show binlog events in 'MysqL-bin.000021';
+------------------+-----+-------------+-----------+-------------+-----------------------------------------------+
| Log_name         | Pos | Event_type  | Server_id | End_log_pos | Info                                          |
| MysqL-bin.000021 |   4 | Format_desc |         1 120 | Server ver: 5.6.31-log,binlog ver: 4         | | Query       195 | BEGIN                                         298 insert into test.t1 values(1,a')             | Xid         329 COMMIT  xid=25 */                           408 515 use `test`; 2,1)">b') 546  xid=33 ----------------+-----+-------------+-----------+-------------+-----------------------------------------------+

 

FORMAT_DESCRIPTION_EVENT

FORMAT_DESCRIPTION_EVENT是binlog version 4中为了取代之前版本中的START_EVENT_V3事件而引入的。它是binlog文件中的第一个事件,而且,该事件只会在binlog中出现一次。MysqL根据FORMAT_DESCRIPTION_EVENT的定义来解析其它事件。

它通常指定了MysqL Server的版本,binlog的版本,该binlog文件的创建时间。

譬如:

# at 
#160817 11:00:10 server id 1  end_log_pos 120 CRC32 0x03010da1     Start: binlog v 4,server v 5.6.31-log created 
# Warning: this binlog is either in use or was not closed properly.
MysqL|
...

 

ROWS_EVENT

对于ROW格式的binlog,所有的DML语句都是记录在ROWS_EVENT中。

ROWS_EVENT分为三种:WRITE_ROWS_EVENT,UPDATE_ROWS_EVENT,DELETE_ROWS_EVENT,分别对应insert,update和delete操作。

对于insert操作,WRITE_ROWS_EVENT包含了要插入的数据

对于update操作,UPDATE_ROWS_EVENT不仅包含了修改后的数据,还包含了修改前的值。

对于delete操作,仅仅需要指定删除的主键(在没有主键的情况下,会给定所有列)

对于QUERY_EVENT事件,是以文本形式记录DML操作的。而对于ROWS_EVENT事件,并不是文本形式,所以在通过MysqLbinlog查看基于ROW格式的binlog时,需要指定-vv --base64-output=decode-rows。

譬如:

MysqLMysqL-bin.000027----------------+-----+-------------+-----------+-------------+---------------------------------------+
| Info                                  000027 188 BEGIN                                 | Table_map   236 | table_id: 80 (test.t1)                | Write_rows  278 80 flags: STMT_END_F        309  xid=198 */                  377 425 | Update_rows 475 506  xid=199 574 622 | Delete_rows 664 695  xid=200 13 rows in set (0.00 sec)

 

XID_EVENT

在事务提交时,不管是STATEMENT还是ROW格式的binlog,都会在末尾添加一个XID_EVENT事件代表事务的结束。该事件记录了该事务的ID,在MysqL进行崩溃恢复时,根据事务在binlog中的提交情况来决定是否提交存储引擎中状态为prepared的事务。

 

ROTATE_EVENT

binlog文件的大小达到max_binlog_size的值或者执行flush logs命令时,binlog会发生切换,这个时候会在当前的binlog日志添加一个ROTATE_EVENT事件,用于指定下一个日志的名称和位置。

MysqLMysqL-bin.000028000028 | Rotate      167 000029;pos=4                2 rows 0.00 sec)
# at 12012:34:26 server 167 CRC32 0xd965567c     Rotate to MysqL-bin.000029  pos: 4

 

GTID_LOG_EVENT

在启用GTID模式后,MysqL实际上为每个事务都分配了个GTID

譬如:

# at 448160818  5:37:32 server 496 CRC32 0xaeb24aac     GTID [commit=yes]
SET @@SESSION.GTID_NEXT= 'cad449f2-5d4f-11e6-b353-000c29c64704:3!;
# at
496571 CRC32 0x042ca092 Query thread_id=2 exec_time=0 error_code= SET TIMESTAMP=1471469852; BEGIN 571674 CRC32 0xa35beb37 Query thread_id=; insert into test.t1 values(2,b) 674705 CRC32 0x1905d8c6 Xid = COMMIT*/;
MysqLMysqL-bin.000033----------------+-----+----------------+-----------+-------------+-------------------------------------------------------------------+
| Event_type     | Info                                                              000033 | Format_desc    4                             | PrevIoUs_gtids 191 | cad449f2-5d4f-11e6-b353-000c29c64704:1                            | Gtid           239 SET @@SESSION.GTID_NEXT= cad449f2-5d4f-11e6-b353-000c29c64704:2' | Query          314 BEGIN                                                             417 ')                                 | Xid            448  xid=11 */                                               496 cad449f2-5d4f-11e6-b353-000c29c64704:3571 674 705  xid=12 | Rotate         752 000034;pos4                                            11 rows PREVIoUS_GTIDS_LOG_EVENT

开启GTID模式后,每个binlog开头都会有一个PREVIoUS_GTIDS_LOG_EVENT事件,它的值是上一个binlog的PREVIoUS_GTIDS_LOG_EVENT+GTID_LOG_EVENT,实际上,在数据库重启的时候,需要重新填充gtid_executed的值,该值即是最新一个binlog的PREVIoUS_GTIDS_LOG_EVENT+GTID_LOG_EVENT。

譬如:

MysqL0.00 sec)

MysqLMysqL-bin.000034----------------+-----+----------------+-----------+-------------+------------------------------------------+
| Info                                     000034 4    1-3 0.00 sec)

MysqL-bin.000033日志中的PrevIoUs_gtids是cad449f2-5d4f-11e6-b353-000c29c64704:1,GTID是cad449f2-5d4f-11e6-b353-000c29c64704:2和cad449f2-5d4f-11e6-b353-000c29c64704:3,这样,在下一个日志,即MysqL-bin.000034中的PrevIoUs_gtids是cad449f2-5d4f-11e6-b353-000c29c64704:1-3。

# at 39:38 server 191 CRC32 0x4e84f3b5     PrevIoUs-GTIDs
# cad449f2-5d4f-11e6-b353-000c29c64704:1-3

 

STOP_EVENT

MysqL数据库停止时,会在当前的binlog末尾添加一个STOP_EVENT事件表示数据库停止。

譬如:

MysqLMysqL-bin.000030000030 | Stop        143 |                                       0.04 sec)
# at 18:04 server 143 CRC32 0xf20ddc85     Stop

 

参考

1. MariaDB原理与实现

2. MysqL官方文档

相关文章

优化MySQL数据库发布系统存储的方法有:1.mysql库主从读写分...
使用mysql的方法:在“我的电脑”→右键→“管理”→“服务”...
在mysql中查看root用户权限的方法:1.命令行启动mysql服务;...
MySQL主从复制是用来备份一个与主数据库一样环境的从数据库,...
运行mysql的方法1.启动mysql服务,在“我的电脑”→右键→“...
开启mysql的方法1.可以通过快捷键win+r,输入cmd,打开窗口,...