230_mysql_binlog結構組成(mysql binlog詳解)
https://dev.Mysql.com/doc/internals/en/event-meanings.html
enum Log_event_type { 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= 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, PRE_GA_WRITE_ROWS_EVENT = 20, PRE_GA_UPDATE_ROWS_EVENT = 21, PRE_GA_DELETE_ROWS_EVENT = 22, WRITE_ROWS_EVENT_V1 = 23, UPDATE_ROWS_EVENT_V1 = 24, DELETE_ROWS_EVENT_V1 = 25, INCIDENT_EVENT= 26, HEARTBEAT_LOG_EVENT= 27, IGNORABLE_LOG_EVENT= 28, ROWS_QUERY_LOG_EVENT= 29, 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, ENUM_END_EVENT /* end marker */ };
1 常見Binlog_event類型
event類型含義
FORMAT_DESCRIPTION_EVENT
每個binlog文件開頭的一個event, 記錄binlog的版本,數據庫版本,創建時間等基本信息
ROTATE_EVENT
1切換新binlog文件:執行FLUSH LOGS語句 or binlog達閾值max_binlog_size意外宕機重啟后會新生成binlog
2 切換新的binlog文件的時候,MySQL會在舊的binlog文件中寫入一個ROTATE_EVENT,表示新的binlog文件的文件名,以及第一個偏移地址。
3宕機前最后一個binlog不是 ROTATE_EVENT結尾
數據庫變更事件
TABLE_MAP_EVENT
TABLE_MAP_EVENT只有在binlog文件是以ROW格式記錄的時候,才會使用。binlog中記錄的每個更改的記錄之前都會有一個對應要操作的表的TABLE_MAP_EVENT。TABLE_MAP_EVENT中記錄了表的定義(包括database name,table name,字段定義),并且會將這個表的定義對應于一個數字,稱為table_id。設計TABLE_MAP_EVENT類型event的目的是為了當主庫和從庫之間有不同的表定義的時候,復制仍能進行。如果一個事務中操作了多個表,多行記錄,在binlog中會將對多行記錄的操作event進行分組,每組行記錄操作event前面會出現對應表的TABLE_MAP_EVENT。
QUERY_EVENT
QUERY_EVENT以文本的形式來記錄事務的操作
QUERY_EVENT類型的事件通常在以下幾種情況下使用:
事務開始時,執行的BEGIN操作。
STATEMENT格式中的DML操作。
ROW格式中的DDL操作。
ROWS_EVENT
對于ROW格式的binlog,所有的DML語句都是記錄在ROWS_EVENT中。
ROWS_EVENT分為三種:WRITE_ROWS_EVENT,UPDATE_ROWS_EVENT,DELETE_ROWS_EVENT
對于QUERY_EVENT事件,是以文本形式記錄DML操作的。而對于ROWS_EVENT事件,并不是文本形式,所以在通過mysqlbinlog查看基于ROW格式的binlog時,需要指定-vv --base64-output=decode-rows
WRITE_ROWS_EVENT
UPDATE_ROWS_EVENT
DELETE_ROWS_EVENT
在以ROW格式記錄的binlog文件中,WRITE_ROWS_EVENT記錄了插入的行記錄
在以ROW格式記錄的binlog文件中,UPDATE_ROWS_EVENT記錄了更新的行記錄
在以ROW格式記錄的binlog文件中,DELETE_ROWS_EVENT記錄了刪除的行記錄
HEARTBEAT_LOG_EVENT
由master發給slave的,讓slave知道master還活著。這類事件不會在binlog或relay log中出現。
他們由master的dump事件線程產生,然后直接發給了slave。slave收到后,校驗事件內容后,直接拋棄這個事件,而不會寫到relay log中
2 event字節解析
在MySQL的發展過程中,一共出現過三個版本的event結構:
v1:在MySQL 3.23中使用
v2:在MySQL4.0.2至4.1中使用
v4:在MySQL5.0及以上版本中使用
3 event組織架構
v4版本的event主要由event header部分和post-header以及variable part部分組成。
event組織架構
event header
是每個event都會有的部分,并且每個event header的格式是相同的,固定為19個字節長度,在event header 中記錄了event_length、type_code等信息,可以表示event的長度,event的類型,下一個event的偏移位置等信息,都可以再event header中獲取到。
extra_headers
指定了除公共頭部外的內容,但是目前版本的binlog格式中,這一部分不存在的
fixed_part & post-header
每個類型的event之間的post-header部分是不相同的,但是同一類型的event占用的post-header
字節數是一樣的。每個類型的event占用多少字節為post-header,這個定義在了Format_description_event中
variable part & body
event真實記錄具體信息的部分;part有些時候也被稱作payload或者body
event字節結構表示如下
timestamp記錄的是該事務記錄的時間
type_code,記錄的是該event的類型,具體的event類型,見上面的Log_event_type
server_id,記錄的是執行該event的server的server_id號
event_length,該event的長度,共占多少字節
next_position,下一個event在binlog文件中的偏移位置
flag:標記
extra_headers,額外的頭部內容,現在是空的,不存在
fixed part有些時候也被稱作post-header
variable part有些時候也被稱作payload或者body
event公共頭部
從上述的event結構中,可以看到,每個event的header部分的內容結構是一致的,所有的event,都會記錄這些信息,這是所有的event的公共頭部分
字段
字節數
描述
timestamp
4字節
時間戳
type_code
1字節
記錄event類型
server_id
4 字節
記錄event生成的MySQL所對應的server_id
event_length
4字節
這個event的字節長度,包括event header
next_position
4字節
下一個event在binlog文件中的偏移位置
flags
2字節
b6 1e 1c 5a //timestamp:小端存儲,將16進制轉換成10進制為1511792310,將時間戳轉換為時間為2017-11-27 22:18:30 1e //type_code:event類型,0x1e轉換為10進制為30,查看Log_event_type中,看到30的為WRITE_ROWS_EVENT 0f 27 00 00 //server_id :小端存儲,將16進制轉換為10進制為9999 31 00 00 00 //event_length :小端存儲,將16進制轉換為10進制為49 b1 03 00 00 //next_position:小端存儲,將16進制轉換為10進制為945 00 00 //flags: body部分省略
Format_description_event
Format_description_event是每個binlog文件開頭的一個描述信息的event
fixed part (post-header) 部分
字段
字節數
描述
binlog_version
2字節
binlog結構的版本,v1,v2,v4
server_version
50字節
MySQL server的數據庫版本
timestamp
4字節
創建該binlog文件的時間,單位為秒
header_length
1字節
指定公共頭部的長度,v4版本中這個值一直為19,說明其他所有的event的extra_header部分都是空, extra_header長度為header_length-19
event_post_header_length
variable size跟各個版本支持的event類型總數一致
每個event類型,占用一個字節,表示該event類型post-header部分的長度
Variable part (event-body)部分
無
字節解析示例 公共頭部部分省略 04 00 //binlog_version :v4版本 35 2e 36 2e 33 34 2d 6c 6f 67 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 //mysql server version :16進制轉換為ascii之后,值為5.6.34-log 00 00 00 00 //timestamp: 13 //header length :19,說明該版本的event類型公共頭部長度都為19,extra_header長度為header_length-19 38 0d 00 08 00 12 00 04 04 04 04 12 00 00 5c 00 04 1a 08 00 00 00 08 08 08 02 00 00 00 0a 0a 0a 19 19 00 //event_post_header_len:各個類型event的post-header部分長度 01 2e ef 23 e2
Rotate_event
當MySQL切換至新的binlog文件的時候,MySQL會在舊的binlog文件中寫入一個ROTATE_EVENT,其內容包含新的binlog文件的文件名以及第一個偏移地址。當在數據庫中執行FLUSH LOGS語句或者binlog文件的大小超過max_binlog_size參數設定的值就會切換新的binlog文件。
fixed part (post-header) 部分
字段
字節數
描述
next_binlog_po
8字節
下一個binlog文件起始的偏移地址
Variable part (event-body)部分
字段
字節數
描述
next_binlog_filename
variable string
下一個binlog文件的文件名
字節解析示例 公共頭部部分省略 04 00 00 00 00 00 00 00 //next_binlog_pos:下一個binlog的起始偏移地址,小端存儲,16進制轉換為10進制之后為4 6d 79 73 71 6c 2d 62 69 6e 2e 30 30 30 30 30 32 //next_binlog_filename:下一個binlog的文件名,16進制轉換為ascii之后,值為mysql-bin.000002 b3 db 0b 9a checksum
Query_log_event
記錄更新操作的語句
fixed part (post-header) 部分
字段
字節數
描述
thread_id
4字節
執行語句的線程ID號
exec_time
4字節
語句執行的時間
db_len
1字節
database名的長度
error_code
2字節
錯誤號
status_vars_len
2字節
在v1和v3版本的event中是沒有的,指定狀態值的長度
Variable part (event-body)部分
字段
字節數
描述
status_vars
status_vars_len字節
記錄狀態值,具體的解析見下表
database_name
db_len+1字節
null-terminaled類型的字符串,記錄database的名字
query_statement
不定
執行的語句
check_sum
4字節
校驗碼
status_vars的解析是,一個字節表示狀態的類型,在類型之后按照類型不同緊接著不同字節數的狀態值,狀態的類型對應狀態碼以及字節數
enum Query_event_status_vars { Q_FLAGS2_CODE= 0, #4字節 Q_SQL_MODE_CODE= 1, #8字節 Q_CATALOG_CODE=2, #第一個字節表示catalog_len,總共catalog_len+2個字節 Q_AUTO_INCREMENT=3, #4字節 Q_CHARSET_CODE=4, #6字節 Q_TIME_ZONE_CODE=5, #第一個字節表示time_zone_len,總共time_zone_len+1字節 Q_CATALOG_NZ_CODE=6, # 第一個字節表示catalog_len,總共catalog_len+1個字節 Q_LC_TIME_NAMES_CODE=7, #2字節 Q_CHARSET_DATABASE_CODE=8, #2字節 Q_TABLE_MAP_FOR_UPDATE_CODE=9, #8字節 Q_MASTER_DATA_WRITTEN_CODE=10, #4字節 Q_INVOKER =11, #包含兩部分,一部分是user,一部分是host。user部分,一個字節表示user_len,接著user_len個字節表示user。host部分,一個字節表示host_len,接著host_len個字節表示host Q_UPDATED_DB_NAMES=12, Q_MICROSECONDS =13, 3字節 Q_COMMIT_TS=14, Q_COMMIT_TS2=15, Q_EXPLICIT_DEFAULTS_FOR_TIMESTAMP=16 1字節 };
解析二進制文件 公共頭部部分省略。。。。 a4 9f 01 00 //thread_id:執行語句的線程號,小端存儲,轉換為16進制為106404 00 00 00 00 //exec_time:執行語句的時間,小端存儲,轉化為16進制為0 08 //db_len:database name的長度,轉換為10進制為8 00 00 //error_code:錯誤號,小端存儲,轉換為10進制為0 2a 00 //status_vars_len:狀態值的長度,小端存儲,轉換為10進制為42,表示后續的42個字節為狀態值的內容 //status_vars_len 00 00 00 00 00 01 00 00 20 40 00 00 00 00 06 03 73 74 64 03 02 00 02 00 04 21 00 21 00 53 00 0c 01 67 61 6e 67 73 68 65 6e 00 67 61 6e 67 73 68 65 6e 00 //database_name:數據庫名稱,null-terminaled string類型 ,轉換為字符串為gangshen 696e7365727420696e746f20746573743128606e616d6560292076616c75657328276265696a696e672729 //query_statement:執行的語句,轉換為字符串為:insert into test1(`name`) values('beijing') 21 92 37 98//checksum
Rows_query_log_event
在row格式復制模式下,將query以語句形式記錄。在5.6.2版本之后,可以通過設置binlog_rows_query_log_events參數來控制在row格式復制模式下是否需要將query語句記錄到binlog文件中。
fixed part (post-header) 部分
無
Variable part (event-body)部分
字段
字節數
描述
str_len
1字節
記錄語句長度
statement
str_len字節
對應的語句
checksum
4字節
校驗碼
解析二進制文件: 公共頭部部分省略。。。 2e //str_len:執行語句的長度,轉換為10進制為46 696e7365727420696e746f20746573743128606e616d6560292076616c7565732827726f77735f71756572792729 //statement:執行的語句,轉換為ascii為insert into test1(`name`) values('rows_query') 8a af 68 dc //check_sum
Table_map_event
TABLE_MAP_EVENT只有在binlog文件是以ROW格式記錄的時候,才會使用。binlog中記錄的每個更改的記錄之前都會有一個對應要操作的表的TABLE_MAP_EVENT。 TABLE_MAP_EVENT中記錄了表的定義(包括database name,table name,字段定義),并且會將這個表的定義對應于一個數字,稱為table_id。 設計TABLE_MAP_EVENT類型event的目的是為了當主庫和從庫之間有不同的表定義的時候,復制仍能進行。 如果一個事務中操作了多個表,多行記錄,在binlog中會將對多行記錄的操作event進行分組,每組行記錄操作event前面會出現對應表的TABLE_MAP_EVENT
fixed part (post-header) 部分
字段
字節數
描述
table_id
6字節
操作的表的table_id
flags
2字節
目前版本沒有用,都是0,保留給之后的版本使用
Variable part (event-body)部分
字段
字節數
描述
database_name
1個字節表示字符串長度,之后接一個null-terminated類型的字符串
操作的數據庫的名稱
dtable_name
1個字節表示字符串長度,之后接一個null-terminated類型的字符串
操作的表的名稱
column_count
packed integer(1或3或4或9個字節)
對應表中的字段數量
column_type
每個字段占用一個字節,字段類型定義在enum_field_types中
字段類型
metadata_length
packed integer(1或3或4或9個字節)
對應字段的元數據信息的長度
metadata
根據enum_field_type中的定義確定不同字段的元數據,如果某字段類型沒有元數據,則不記錄
每個字段的元數據信息,比如varchar字段需要記錄最長長度
null_bits
int((column_count + 7)/8) 字節
一個bit表示一個字段是否可以為NULL,順序是:第一個字節的最低位開始向最高位增長,之后第二個字節的最低位開始向最高位增長,以此類推
check_sum
4字節
校驗碼
CREATE TABLE `test1` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(20) COLLATE utf8_bin DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8 COLLATE=utf8_bin
二進制內容解析: 公共頭部部分省略 6c 00 00 00 00 00 //table_id :小端存儲,16進制轉換為10進制為108 01 00 //flag : 08 67 61 6e 67 73 68 65 6e 00 //database_name :1個字節是字符串長度,后接一個null-terminated string 第一個字節表示字符串長度為8,后面內容將16進制轉換為ascii字符為gangshen 05 74 65 73 74 31 00 //table_name: 1個字節是字符串長度,后接一個null-terminated string第一個字節表示字符串長度為5,后面內容將16進制轉換為ascii字符為test1 02 //columns count :packet integer類型,轉換之后,數值為2 表示表中有兩個字段 03 0f //column type : 一個字節表示一個字段的類型,字段類型定義在enum enum_field_types ,分別是一個int類型以及一個varchar類型,具體的字段類型及記錄格式等信息可以查看《MySQL中Rows_event中字段表示》文檔 02 //metadata length : packet integer類型,轉換之后,數值為2,表示記錄表中的metadata內容占用2個字節 14 00 // :varchar 的max length 因為int沒有metadata所以跳過 02 //null_bits :int((column_count + 7) / 8)個字節 一個bit表示一個字段是否可以為null 52 53 4a d9 checksum
Write_rows_log_event
在以ROW格式記錄的binlog文件中,Write_rows_log_event記錄了插入的行記錄
fixed part (post-header) 部分
字段
字節數
描述
table_id
6字節
操作的表的table_id
flags
2字節
目前版本沒有用,都是0,保留給之后的版本使用
Variable part (event-body)部分
字段
字節數
描述
var_header
2字節
m_width
packed integer(1或3或4或9個字節)
表中字段數量
before_image
(m_width + 7)/8字節
對應表中的字段數量
after_bitmap_bits
(m_with +7)/8字節
字段值是否為空標記,一個bit表示一個字段是否為NULL,順序是:第一個字節的最低位開始向最高位增長,之后第二個字節的最低位開始向最高位增長,以此類推
after_column_content
不定
按照順序每個字段的內容
check_sum
4字節
校驗碼
建表語句 CREATE TABLE `int_table` ( `col1` tinyint(4) DEFAULT NULL, `col2` smallint(6) DEFAULT NULL, `col3` mediumint(9) DEFAULT NULL, `col4` int(11) DEFAULT NULL, `col5` bigint(20) DEFAULT NULL, `col6` tinyint(1) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin 插入數據: insert into int_table values(1,11,111,1111,11111,true);
對應Write_rows_log_event使用mysqlbinlog解析 # at 340 #180103 10:21:20 server id 330619 end_log_pos 395 CRC32 0x50177e10 Write_rows: table id 100 flags: STMT_END_F ### INSERT INTO `gangshen`.`int_table` ### SET ### @1=1 /* TINYINT meta=0 nullable=1 is_null=0 */ ### @2=11 /* SHORTINT meta=0 nullable=1 is_null=0 */ ### @3=111 /* MEDIUMINT meta=0 nullable=1 is_null=0 */ ### @4=1111 /* INT meta=0 nullable=1 is_null=0 */ ### @5=11111 /* LONGINT meta=0 nullable=1 is_null=0 */ ### @6=1 /* TINYINT meta=0 nullable=1 is_null=0 */ # at 395
公共頭部部分省略 64 00 00 00 00 00 //table_id: 小端存儲,16進制轉換為10進制為100 01 00 //flag: 02 00 //var header length :小端存儲,16進制轉換為10進制為2 06 //m_width :packet integer,表示表中字段數量 ff //before image: (m_width + 7) / 8字節 c0 //after_bitmap_bits :insert插入之后的記錄的NULL標記,表中六個字段,插入的值都不為NULL //after_columns_content:insert插入記錄之后的記錄值 01 0b 00 6f 00 00 57 04 00 00 67 2b 00 00 00 00 00 00 01 10 7e 17 50 //checksum
Update_rows_log_event
在以ROW格式記錄的binlog文件中,Update_rows_log_event記錄了更新的行記錄。
fixed part (post-header) 部分
字段
字節數
描述
table_id
6字節
操作的表的table_id
flags
2字節
目前版本沒有用,都是0,保留給之后的版本使用
Variable part (event-body)部分
字段
字節數
描述
var_header
2字節
m_width
packed integer(1或3或4或9個字節)
表中字段數量
before_image
(m_width + 7)/8字節
對應表中的字段數量
after_image _image
(m_width + 7)/8字節
對應表中的字段數量
before_bitmap_bits
(m_with+7)/8字節
before_bitmap_bits記錄的是update更改之前的記錄中,字段值是否為NULL標記,一個bit表示一個字段是否為NULL,順序是:第一個字節的最低位開始向最高位開始增長,之后第二個字節的最低位開始向最高位增長,以此類推
before_column_content
不定
update更新之前的記錄值,按照順序每個字段的內容
after_bitmap_bits
(m_with +7)/8字節
after_bitmap_bits記錄的是update更改之前的記錄中,字段值是否為NULL標記,一個bit表示一個字段是否為NULL,順序是:第一個字節的最低位開始向最高位開始增長,之后第二個字節的最低位開始向最高位增長,以此類推
after_column_content
不定
update更新之后的記錄值,按照順序每個字段的內容
check_sum
4字節
校驗碼
字節解析示例 建表語句 CREATE TABLE `int_table` ( `col1` tinyint(4) DEFAULT NULL, `col2` smallint(6) DEFAULT NULL, `col3` mediumint(9) DEFAULT NULL, `col4` int(11) DEFAULT NULL, `col5` bigint(20) DEFAULT NULL, `col6` tinyint(1) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin 插入數據并更新: insert into int_table values(1,11,111,1111,11111,true); update int_table set col2=22,col3=222 where col1=1;
對應Update_rows_log_event使用mysqlbinlog解析 # at 644 #180103 10:41:37 server id 9999 end_log_pos 720 CRC32 0x5576b52f Update_rows: table id 231 flags: STMT_END_F ### UPDATE `gangshen`.`int_table` ### WHERE ### @1=1 /* TINYINT meta=0 nullable=1 is_null=0 */ ### @2=11 /* SHORTINT meta=0 nullable=1 is_null=0 */ ### @3=111 /* MEDIUMINT meta=0 nullable=1 is_null=0 */ ### @4=1111 /* INT meta=0 nullable=1 is_null=0 */ ### @5=11111 /* LONGINT meta=0 nullable=1 is_null=0 */ ### @6=1 /* TINYINT meta=0 nullable=1 is_null=0 */ ### SET ### @1=1 /* TINYINT meta=0 nullable=1 is_null=0 */ ### @2=22 /* SHORTINT meta=0 nullable=1 is_null=0 */ ### @3=222 /* MEDIUMINT meta=0 nullable=1 is_null=0 */ ### @4=1111 /* INT meta=0 nullable=1 is_null=0 */ ### @5=11111 /* LONGINT meta=0 nullable=1 is_null=0 */ ### @6=1 /* TINYINT meta=0 nullable=1 is_null=0 */ # at 720
解析二進制文件: 公共頭部部分省略。。。 64 00 00 00 00 00 //table_id: 小端存儲,16進制轉換為10進制為100 01 00 //flag: 02 00 //var header length :小端存儲,16進制轉換為10進制為2 06 //m_width :packet integer,表示表中字段數量 ff //before image: (m_width + 7) / 8字節 ff //after image: (m_width + 7) / 8字節 c0 //before_bitmap_bits :update更新之前記錄中NULL標記,表中六個字段,值都不為NULL //before_column_content接下來是update更新之前記錄的值 01 0b 00 6f 00 00 57 04 00 00 67 2b 00 00 00 00 00 00 01 c0 //after_bitmap_bits :update更新之后記錄中NULL標記,表中六個字段,值都不為NULL //after_column_content接下來是update更新之前記錄的值 01 16 00 de 00 00 57 04 00 00 67 2b 00 00 00 00 00 00 01 16 a3 de bb //checksum
Delete_rows_log_event
在以ROW格式記錄的binlog文件中,Delete_rows_log_event記錄了刪除的行記錄。
fixed part (post-header) 部分
字段
字節數
描述
table_id
6字節
操作的表的table_id
flags
2字節
目前版本沒有用,都是0,保留給之后的版本使用
Variable part (event-body)部分
字段
字節數
描述
var_header
2字節
m_width
packed integer(1或3或4或9個字節)
表中字段數量
after_image _image
(m_width + 7)/8字節
對應表中的字段數量
before_bitmap_bits
(m_with+7)/8字節
before_bitmap_bits記錄的是update更改之前的記錄中,字段值是否為NULL標記,一個bit表示一個字段是否為NULL,順序是:第一個字節的最低位開始向最高位開始增長,之后第二個字節的最低位開始向最高位增長,以此類推
before_column_content
不定
delete刪除之前的記錄值,按照順序每個字段的內
check_sum
4字節
校驗碼
建表語句 CREATE TABLE `int_table` ( `col1` tinyint(4) DEFAULT NULL, `col2` smallint(6) DEFAULT NULL, `col3` mediumint(9) DEFAULT NULL, `col4` int(11) DEFAULT NULL, `col5` bigint(20) DEFAULT NULL, `col6` tinyint(1) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin 刪除數據: delete from int_table where col1=1;
對應Delete_rows_log_event使用mysqlbinlog解析 # at 320 #180103 14:24:54 server id 330619 end_log_pos 375 CRC32 0xce4818b2 Delete_rows: table id 100 flags: STMT_END_F ### DELETE FROM `gangshen`.`int_table` ### WHERE ### @1=1 /* TINYINT meta=0 nullable=1 is_null=0 */ ### @2=22 /* SHORTINT meta=0 nullable=1 is_null=0 */ ### @3=222 /* MEDIUMINT meta=0 nullable=1 is_null=0 */ ### @4=1111 /* INT meta=0 nullable=1 is_null=0 */ ### @5=11111 /* LONGINT meta=0 nullable=1 is_null=0 */ ### @6=1 /* TINYINT meta=0 nullable=1 is_null=0 */ # at 375
解析二進制文件: 公共頭部部分省略 64 00 00 00 00 00 //table_id: 小端存儲,16進制轉換為10進制為100 01 00 //flag: 02 00 //var header length :小端存儲,16進制轉換為10進制為2 06 //m_width :packet integer,表示表中字段數量 ff //after image: (m_width + 7) / 8字節 c0 //before_bitmap_bits :delete刪除之前的記錄的NULL標記,表中六個字段,值都不為NULL //before_columns_content:delete刪除記錄之前的記錄值 01 16 00 de 00 00 57 04 00 00 67 2b 00 00 00 00 00 00 01 10 7e 17 50 //checksum
Xid_event
表示支持內部XA的存儲引擎上的事務提交。正常的事務是通過QUERY_EVENT來發送一個BEGIN語句并且通過QUERY_EVENT來發送一個COMMIT語句(如果事務回滾則發送的是ROLLBACK)實現
fixed part (post-header) 部分
無
Variable part (event-body)部分
字段
字節數
描述
xid
8字節
無符號數
after_image _image
(m_width + 7)/8字節
對應表中的字段數量
# at 1691 #180103 15:30:45 server id 330619 end_log_pos 1722 CRC32 0x8816181c Xid = 2698 COMMIT/*!*/; # at 1722
解析二進制文件: 公共頭部部分省略... 8a 0a 00 00 00 00 00 00 //xid,因為是小端存儲,所以實際為0x 00 00 00 00 00 00 0a 8a,轉換為10進制為2698 1c 18 16 88 //check_sum
Gtid_log_event
開啟GTID模式的場景下,每次事務commit提交時,MySQL會在binlog中事務開始寫入一個Gtid_log_event,記錄該事務的GTID事務號。
fixed part (post-header) 部分
字段
字節數
描述
commit_flag
1字節
標記事務是否提交,非0為已提交,為0表示,事務未提交
sid
16字節
記錄GTID中uuid的部分(不記錄‘-’),每1個字節表示uuid中2個字符
gno
8字節
小端存儲,GTID中的事務號部分
Variable part (event-body)部分
字段
字節數
描述
checksum??????? 4
4字節
校驗碼
字節解析示例 使用mysqlbinlog工具解析binlog文件 # at 191 #180109 18:31:08 server id 330619 end_log_pos 239 CRC32 0xd20330e8 GTID [commit=yes] SET @@SESSION.GTID_NEXT= '89fbcea2-da65-11e7-a851-fa163e618bac:5'/*!*/; # at 239 解析二進制文件: 公共頭部部分省略。。。。 01 //commit_flag:標記事務是否已提交,表示已提交 89 fb ce a2 da 65 11 e7 a8 51 fa 16 3e 61 8b ac //sid:GTID中uuid部分,轉換為uuid為89fbcea2-da65-11e7-a851-fa163e618bac 05 00 00 00 00 00 00 00 //gno:GTID中的事務號,小端存儲,轉換為10進制為5 e8 30 03 d2 //checksum
Previous_gtid_log_event
在開啟GTID的模式下,每個binlog文件開始會記錄一個Previous_gtid_log_event,Previous_gtid_log_event中會包含當前binlog之前所有binlog中的GTID集合
fixed part (post-header) 部分
字段
字節數
描述
n_sids
8字節
小端存儲,記錄之后有幾個GTID中的uuid號
sid
16字節
記錄GTID中uuid的部分(不記錄‘-’),每1個字節表示uuid中2個字符
n_intervals
8字節
記錄每個sid對應有幾個間隔,指的是事務號間隔
start
8字節
每個事務號間隔中的起始事務號
end
8字節
每個事務號間隔中的結束事務號+1
Variable part (event-body)部分
字段
字節數
描述
checksum??????? 4
4字節
校驗碼
字節解析示例 使用mysqlbinlog工具解析binlog文件 # at 120 #180111 14:10:27 server id 330619 end_log_pos 279 CRC32 0x94a92478 Previous-GTIDs # 89fbcea2-da65-11e7-a851-fa163e618bac:1-5:999:1050-1052, # aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1-2:5-7 DELIMITER ; 解析二進制文件: 公共頭部部分省略。。。 02 00 00 00 00 00 00 00 //n_sids:記錄之后有幾個GTID中的uuid號,小端存儲,轉換為10進制為2,表后后續有2個uuid號 89 fb ce a2 da 65 11 e7 a8 51 fa 16 3e 61 8b ac //sid:GTID中的uuid號轉換為uuid為89fbcea2-da65-11e7-a851-fa163e618bac 03 00 00 00 00 00 00 00 //n_intervals:對應的sid中中對應幾個事務號間隔,小端存儲,轉換為10進制為3,表示有3個事務號間隔 01 00 00 00 00 00 00 00 //start:事務號間隔中的起始事務號,小端存儲,轉換為10進制為1 06 00 00 00 00 00 00 00 //end:事務號間隔中的結束事務號+1,小端存儲,轉換為10進制為6,實際的間隔結束事務號為5 e7 03 00 00 00 00 00 00 //start:事務號間隔中的起始事務號,小端存儲,轉換為10進制為999 e8 03 00 00 00 00 00 00 //end:事務號間隔中的結束事務號+1,小端存儲,轉換為10進制為1000,實際的間隔結束事務號為999 1a 04 00 00 00 00 00 00 //start:事務號間隔中的起始事務號,小端存儲,轉換為10進制為1050 1d 04 00 00 00 00 00 00 //end:事務號間隔中的結束事務號+1,小端存儲,轉換為10進制為1053,實際的間隔結束事務號為1052 aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa //sid:GTID中的uuid號轉換為uuid為aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 02 00 00 00 00 00 00 00 //n_intervals:對應的sid中中對應幾個事務號間隔,小端存儲,轉換為10進制為2,表示有2個事務號間隔 01 00 00 00 00 00 00 00 //start:事務號間隔中的起始事務號,小端存儲,轉換為10進制為1 03 00 00 00 00 00 00 00 //end:事務號間隔中的結束事務號+1,小端存儲,轉換為10進制為3,實際的間隔結束事務號為2 05 00 00 00 00 00 00 00 //start:事務號間隔中的起始事務號,小端存儲,轉換為10進制為5 08 00 00 00 00 00 00 00 //end:事務號間隔中的結束事務號+1,小端存儲,轉換為10進制為8,實際的間隔結束事務號為7 78 24 a9 94 //checksum
Anonymous_gtid_log_event
MySQL在binlog中記錄每一個匿名事務之前會記錄一個Anonymous_gtid_log_event表示接下來的事務是一個匿名事務。
注意:因為在5.6.34中并不會產生Anonymous_gtid_log_event,所以以下內容是基于5.7.19版本解析
fixed part (post-header) 部分
字段
字節數
描述
gtid_flags
1字節
記錄binlog格式,如果gtid_flags值為1,表示binlog中可能有以statement方式記錄的binlog,如果為0表示,binlog中只有以row格式記錄的binlog
sid
16字節
記錄GTID中uuid的部分(不記錄‘-’),每1個字節表示uuid中2個字符
gno
8字節
GTID中的事務號部分
logical_timestamp_typecode
1字節
判斷是否有last_commit和sequence_no,在logical_tmiestamp_typecode=2的情況下,有last_commit和sequence_no
last_commit
8字節
上次提交的事務號
sequence_no
8字節
本次提交的序列號
Variable part (event-body)部分
字段
字節數
描述
checksum??????? 4
4字節
校驗碼
字節解析示例 使用mysqlbinlog工具解析binlog文件 #180109 10:53:54 server id 9999 end_log_pos 5681 CRC32 0x46be0639 Anonymous_GTID last_committed=20 sequence_number=21 rbr_only=yes /*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/; SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/; # at 5681 解析二進制文件: 公共頭部部分省略。。。 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 //sid: 00 00 00 00 00 00 00 00 //gno: 02 //logical_timestamp_typecode:判斷是否有last_commit和sequence_no,在logical_tmiestamp_typecode=2的情況下,有last_commit和sequence_no,所以這邊的話,后續有last_commit和sequence_no部分的內容 14 00 00 00 00 00 00 00 //last_commit:上次提交的事務號,小端存儲,轉換為10機制為20 15 00 00 00 00 00 00 00 //sequence_no:本次提交的序列號,小端存儲,轉換為10進制為21 39 06 be 46 //checksum:校驗碼
MySQL 數據庫
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。