mysql binlog解析 c_mysql binlog格式解析(一)

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼

参考源:

1、源码log_event.h log_event.cc pack.c

2、internals-en.epub

一、目的

本系列文件主要为了说明

1、为什么说row格式较statement更占空间

2、为什么说row格式的binlog更加安全

3、INSERT/UPDATE/DELETE是生成的row binlog如何直接看懂二进制格式

4、DDL生成的binlog是怎么样的

5、INSERT SELECT/CREATE TABLE 如何生成的row binlog

二、使用版本和数字显示

本系列文章重要解释MYSQL 5.6后row格式的binlog格式以及和事物有关的event,按照官方的说法

binlog的格式经历了几个阶段

v1:mysql 3.23

v3:mysql 4.0.2 到 4.1

v4:mysql 5.0以上

v2版本只是短暂的存在过,当然我们要解析当然是v4版本的binlog

因为要看是5.6以上的binlog

关于多字节的数字显示,一般使用 Little-endian模式,做到和OS系统无关,除非刻意说明

关于Little-endian参考:

http://blog.itpub.net/7728585/viewspace-2124159/

三、binlog的魔法数

关于MYSQL BINLOG的作用就不做过多的解析了,在binlog中存储的是一种称之为event的条目,

它们以二进制的格式存储,平时我们使用的mysqlbinlog工具也就是对这种二进制格式的文件

进行解析,得到直观的输出。这里不用mysqlbinlog而改为直接看二进制文件,当然我会对比

MYSQLBINLOG的输出和二进制解析的过程

每一个binlog文件都有4字节的魔法数,其值固定为

[root@testmy mysqld.1]# hexdump -Cv test.000005

可以看到

fe 62 69 6e .bin

四、binlog event的总体构架

一个event包括了

event header

event data

其中event data又分为

fixed data(posted header)

variable data

event header:全部的event统一固定的格式

fixed data(posted header):每一类event固定

variable data:就是可以变化实际值了

关于event的类型比较多详细参考末尾源码的截取

五、本系列文章要讨论的event

而这里我们只要讨论5.6,5.7中和row binlog格式和innodb

联系比较紧密的几种event如下:

query_log_event/QUERY_EVENT typecode=02

Format_description_log_event/FORMAT_DESCRIPTION_EVENT typecode=15

Xid_log_event/XID_EVENT typecode=16

Table_map_log_event/TABLE_MAP_EVENT typecode=19

Write_rows_log_event/WRITE_ROW_EVENT typecode=30

Update_rows_log_event/UPDATE_ROW_EVENT typecode=31

Delele_rows_log_event/DELETE_ROW_EVENT typecode=32

因为这些语句是一个事物必须经历的,而Format_description_log_event是一个最重要的

说明性的event

六、通用头文件(event header)解析

下面先解释一下通用的19个字节。

每一个event有一个固定的头信息叫做event header:

event header

timestamp 0:4

type_code 4:1

server_id 5:4

event_length 9:4

next_position 13:4

flags 17:2

timestamp:固定4字节展示是新纪元(epoch time)以来的秒数

type_code:固定1字节event事件的编码,在源码中是一个enum类型负载最后源码处

server_id:固定4字节就是 show variables like '%server_id';出来的值

event_length:固定4字节整个event的长度,包含固定和非固定长度

next_position:固定4字节下一个event的开始位置(2^32为4G)

flags:固定2字节 event flags

LOG_EVENT_BINLOG_IN_USE_F 0x1 这个flags表示是否binlog正确的关闭了,这个标示只出现在Format_description_log_event中

LOG_EVENT_THREAD_SPECIFIC_F 0x4 是否查询基于了临时表,如果基于了临时表MYSQLBINLOG必须设置 @@PSEUDO_THREAD_ID=xx

LOG_EVENT_SUPPRESS_USE_F 0x8 和--binlog-do-db 、 --replicated-do-db有关

其他还有很多

LOG_EVENT_ARTIFICIAL_F 0x20 LOG_EVENT_RELAY_LOG_F 0x40 LOG_EVENT_IGNORABLE_F 0x80 LOG_EVENT_NO_FILTER_F 0x100 。。。

可以自行参考log_event.h源码头文件中的详细解释

七、packed interger

在binlog中部分数字使用这种方式显示,在后面的解析中会提到

按照文档和源码中的说明

如果第一个字节为0-250及0X0-0XFA那么这个字节就是实际显示的数字值

源码的:

if (length < (ulonglong) LL(251))

{

*packet=(uchar) length;

return packet+1;

}

如果第一个字节为252及0XFC那么后面的2个字节的值为0XFB-0XFFFF

源码的:

if (length < (ulonglong) LL(65536))

{

*packet++=252;

int2store(packet,(uint) length);

return packet+2;

}

如果第一个字节为253及0XFD那么后面的3个字节的值为0XFFFF-0XFFFFFF

源码的:

if (length < (ulonglong) LL(16777216))

{

*packet++=253;

int3store(packet,(ulong) length);

return packet+3;

}

如果第一个字节为254及0XFE那么后面的8个字节的值为0XFFFFFF-0XFFFFFFFFFFFFFFFF

*packet++=254;

int8store(packet,length);

可以自行参考源码接口,函数返回值为一个下一个位置的指针

uchar *net_store_length(uchar *packet, ulonglong length)

点击(此处)折叠或打开

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= 1,

QUERY_EVENT= 2,

STOP_EVENT= 3,

ROTATE_EVENT= 4,

INTVAR_EVENT= 5,

LOAD_EVENT= 6,

SLAVE_EVENT= 7,

CREATE_FILE_EVENT= 8,

APPEND_BLOCK_EVENT= 9,

EXEC_LOAD_EVENT= 10,

DELETE_FILE_EVENT= 11,

/**

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= 12,

RAND_EVENT= 13,

USER_VAR_EVENT= 14,

FORMAT_DESCRIPTION_EVENT= 15,

XID_EVENT= 16,

BEGIN_LOAD_QUERY_EVENT= 17,

EXECUTE_LOAD_QUERY_EVENT= 18,

TABLE_MAP_EVENT = 19,

/**

The PRE_GA event numbers were used for 5.1.0 to 5.1.15 and are

therefore obsolete.

*/

PRE_GA_WRITE_ROWS_EVENT = 20,

PRE_GA_UPDATE_ROWS_EVENT = 21,

PRE_GA_DELETE_ROWS_EVENT = 22,

/**

The V1 event numbers are used from 5.1.16 until mysql-trunk-xx

*/

WRITE_ROWS_EVENT_V1 = 23,

UPDATE_ROWS_EVENT_V1 = 24,

DELETE_ROWS_EVENT_V1 = 25,

/**

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= 28,

ROWS_QUERY_LOG_EVENT= 29,

/** Version 2 of the Row events */

WRITE_ROWS_EVENT = 30,

UPDATE_ROWS_EVENT = 31,

DELETE_ROWS_EVENT = 32,

GTID_LOG_EVENT= 33,

ANONYMOUS_GTID_LOG_EVENT= 34,

PREVIOUS_GTIDS_LOG_EVENT= 35,

TRANSACTION_CONTEXT_EVENT= 36,

VIEW_CHANGE_EVENT= 37,

/* Prepared XA transaction terminal event similar to Xid */

XA_PREPARE_LOG_EVENT= 38,

/**

Add new events here - right above this

Existing events (except ENUM_END_EVENT) should never change their numbers

*/

ENUM_END_EVENT /* end marker */

};

你可能感兴趣的:(mysql,binlog解析,c)