解析MYSQL BINLOG 二進位制格式(5)--WRITE_ROW_EVENT
原創:轉載請說明出處謝謝!
上接
http://blog.itpub.net/7728585/viewspace-2133188/ 解析MYSQL BINLOG 二進位制格式(1)--準備工作
http://blog.itpub.net/7728585/viewspace-2133189/ 解析MYSQL BINLOG 二進位制格式(2)--FORMAT_DESCRIPTION_EVENT
http://blog.itpub.net/7728585/viewspace-2133321/ 解析MYSQL BINLOG 二進位制格式(3)--QUERY_EVENT
http://blog.itpub.net/7728585/viewspace-2133429/ 解析MYSQL BINLOG 二進位制格式(4)--TABLE_MAP_EVENT
class:Write_rows_log_event
event:WRITE_ROW_EVENT
event_code:30
自從5.1.18開始,row模式下的insert的event,為什麼要叫write不叫insert
呢無賴...
這部分在internals文件中有點小的問題,我也是看了原始碼的描述才找到,
在文件中也寫到[TODO:following needs verification;it's guesswork]
就是fixed data中有2 bytes的m_extra_row_data其值當前為
uint16 vhlen= 2;
uint16 vhpayloadlen= 0;
下面有部分原始碼擷取。如果不知道這兩個位元組讀取就會有問題。至少5.6,5.7都有的
老版本我也沒有驗證。
--fixed data 10位元組(5.6,5.7中描述為 ROWS_HEADER_LEN_V2)
6 bytes 表ID
2 bytes 保留
2 bytes 文件中並沒有描述
原始碼中描述為:
uchar *m_extra_row_data; /* Pointer to extra row data if any */
/* If non null, first byte is length */
原始碼中是這樣寫入的:
if (likely(!log_bin_use_v1_row_events))
{
/*
v2 event, with variable header portion.
Determine length of variable header payload
*/
uint16 vhlen= 2;
uint16 vhpayloadlen= 0;
uint16 extra_data_len= 0;
if (m_extra_row_data)
{
extra_data_len= m_extra_row_data[EXTRA_ROW_INFO_LEN_OFFSET];
vhpayloadlen= RW_V_TAG_LEN + extra_data_len;
}
/* Var-size header len includes len itself */
int2store(buf + RW_VHLEN_OFFSET, vhlen + vhpayloadlen);
rc= wrapper_my_b_safe_write(file, buf, ROWS_HEADER_LEN_V2);
/* Write var-sized payload, if any */
if ((vhpayloadlen > 0) &&
(rc == 0))
{
/* Add tag and extra row info */
uchar type_code= RW_V_EXTRAINFO_TAG;
rc= wrapper_my_b_safe_write(file, &type_code, RW_V_TAG_LEN);
if (rc==0)
rc= wrapper_my_b_safe_write(file, m_extra_row_data, extra_data_len);
}
}
else
{
rc= wrapper_my_b_safe_write(file, buf, ROWS_HEADER_LEN_V1);
}
可以看到實際上寫入的就是
uint16 vhlen= 2;
uint16 vhpayloadlen= 0;
有興趣可以參考原始碼:
Rows_log_event::write_data_header(IO_CACHE *file)
--variable data part
packed integer:表中欄位個數,這個地方為packed integer自行參考原始碼
uchar *net_store_length
var-size:文件解釋為每一位代表是否欄位用到了 長度為INT((n+7)/8) n代表欄位數量
原始碼描述為 m_cols; /* Bitmap denoting columns available */
測試表現這一位元組和binlog_row_image設定有關,預設為FULL每一個位元組始終為
0XFF
var-size:每一位代表的欄位的值是否為NULL,長度為INT((n+7)/8) n代表欄位數量,
他採用一個點陣圖的方式。
1:NULL
0:NOT NULL
var-size:這部分就是真正的資料了。
為了驗證我做了如下的測試表:
mysql> create table testnull2 (id int,name1 varchar(20),name2 varchar(20));
Query OK, 0 rows affected (0.09 sec)
mysql> insert into testnull2 values(NULL,'test',NULL);
Query OK, 1 row affected (0.01 sec)
可以看到我只是插入的資料第一個欄位第三個欄位都是NULL,好我們看是解析,這次試用
mysqlbinlog 自帶的--hexdump方式和自己開發的工具./infobin,這個工具就是透過自己
對binlog event的認知進行解析的,做這個工具的目的在於簡化和友好的輸出,方便我以後
的測試使用,同時也驗證了我的全部說法,有時候mysqlbinlog的輸出有點過於繁多,不便於
描述和測試,關於XID_EVENT和GTID_EVENT在後面描述
關於工具我放到了百度雲盤
[root@testmy data]# ./infobin test.000183
Check is Little_endian
Author: gaopeng QQ:22389860 Mail: gaopp_200217@163.com
Waring: This tool only Little_endian platform!
Little_endian check ok!!!
-------------Now begin--------------
Check Mysql Version is:5.7.13-log
Check Mysql binlog format ver is:V4
------------Detail now--------------
>Gtid Event:Pos:194(0Xc2) N_pos:259(0X103) Time:1486946663 Event_size:65(bytes)
Gtid:4a6f2a67-5d87-11e6-a6bd-0c29a879a3:1000448
-->Query Event:Pos:259(0X103) N_Pos:400(0X190) Time:1486946663 Event_size:141(bytes)
Exe_time:0 Use_db:test Statment(35b-trun):create table testnull2 (id int,name
>Gtid Event:Pos:400(0X190) N_pos:465(0X1d1) Time:1486946680 Event_size:65(bytes)
Gtid:4a6f2a67-5d87-11e6-a6bd-0c29a879a3:1000449
-->Query Event:Pos:465(0X1d1) N_Pos:537(0X219) Time:1486946680 Event_size:72(bytes)
Exe_time:0 Use_db:test Statment(35b-trun):BEGIN
---->Map Event:Pos537(0X219) N_pos:595(0X253) Time:1486946680 Event_size:58(bytes)
TABLE_ID:210 DB_NAME:test TABLE_NAME:testnull2
------>Insert Event:Pos:595(0X253) N_pos:636(0X27c) Time:1486946680 Event_size:41(bytes)
Dml on table: test.testnull2 table_id:210 Gno:1000449
>Xid Event:Pos:636(0X27c) N_Pos:667(0X29b) Time:1486946680 Event_size:31(bytes)
COMMIT 1000449 /*!add by tool*/
這裡找到了insert event:
------>Insert Event:Pos:595(0X253) N_pos:636(0X27c) Time:1486946680 Event_size:41(bytes)
Dml on table: test.testnull2 Gno:1000449
這裡這個event的開始位置為595
進行使用mysqlbinlog --hexdump格式
# at 595
#170213 8:44:40 server id 93157 end_log_pos 636 CRC32 0x32dd470a
# Position Timestamp Type Master ID Size Master Pos Flags
# 253 78 01 a1 58 1e e5 6b 01 00 29 00 00 00 7c 02 00 00 00 00
# 266 d2 00 00 00 00 00 01 00 02 00 03 ff fd 04 74 65 |..............te|
# 276 73 74 0a 47 dd 32 |st.G.2|
# Write_rows: table id 210 flags: STMT_END_F
下面是-vv的輸出
### INSERT INTO `test`.`testnull2`
### SET
### @1=NULL /* type=3 meta=0 nullable=1 is_null=1 */
### @2='test' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */
### @3=NULL /* VARSTRING(60) meta=60 nullable=1 is_null=1 */
分解:
--event header 部分就不解析了table id 210,
--hexdump也明確的解析了,不理解參考前面的文章
# Position Timestamp Type Master ID Size Master Pos Flags
# 253 78 01 a1 58 1e e5 6b 01 00 29 00 00 00 7c 02 00 00 00 00
--fixed data
d2 00 00 00 00 00:表ID就是./infobin中的TABLE_ID:210 也是mysqlbinlog中的Write_rows: table id 210
01 00:保留
02 00:m_extra_row_data,這部分是我看原始碼找到的。
--variable data part
03:表中欄位個數,當然我建表就是3個欄位
ff: 原始碼描述為 m_cols; /* Bitmap denoting columns available */
fd: 11111101 代表欄位@1=NULL和@3=NULL,但是欄位@2不為空這和mysqlbinlog解析的一致
@1=NULL /* type=3 meta=0 nullable=1 is_null=1 */
@2='test' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */
@3=NULL /* VARSTRING(60) meta=60 nullable=1 is_null=1 */
04:var 長度04 就是資料'test'的長度為4,當然為4
74 65 73 74:字串'test'
ca 3f c1 05:crc 32校驗
到此為止WRITE_ROW_EVENT解析完畢
上接
http://blog.itpub.net/7728585/viewspace-2133188/ 解析MYSQL BINLOG 二進位制格式(1)--準備工作
http://blog.itpub.net/7728585/viewspace-2133189/ 解析MYSQL BINLOG 二進位制格式(2)--FORMAT_DESCRIPTION_EVENT
http://blog.itpub.net/7728585/viewspace-2133321/ 解析MYSQL BINLOG 二進位制格式(3)--QUERY_EVENT
http://blog.itpub.net/7728585/viewspace-2133429/ 解析MYSQL BINLOG 二進位制格式(4)--TABLE_MAP_EVENT
class:Write_rows_log_event
event:WRITE_ROW_EVENT
event_code:30
自從5.1.18開始,row模式下的insert的event,為什麼要叫write不叫insert
呢無賴...
這部分在internals文件中有點小的問題,我也是看了原始碼的描述才找到,
在文件中也寫到[TODO:following needs verification;it's guesswork]
就是fixed data中有2 bytes的m_extra_row_data其值當前為
uint16 vhlen= 2;
uint16 vhpayloadlen= 0;
下面有部分原始碼擷取。如果不知道這兩個位元組讀取就會有問題。至少5.6,5.7都有的
老版本我也沒有驗證。
--fixed data 10位元組(5.6,5.7中描述為 ROWS_HEADER_LEN_V2)
6 bytes 表ID
2 bytes 保留
2 bytes 文件中並沒有描述
原始碼中描述為:
uchar *m_extra_row_data; /* Pointer to extra row data if any */
/* If non null, first byte is length */
原始碼中是這樣寫入的:
if (likely(!log_bin_use_v1_row_events))
{
/*
v2 event, with variable header portion.
Determine length of variable header payload
*/
uint16 vhlen= 2;
uint16 vhpayloadlen= 0;
uint16 extra_data_len= 0;
if (m_extra_row_data)
{
extra_data_len= m_extra_row_data[EXTRA_ROW_INFO_LEN_OFFSET];
vhpayloadlen= RW_V_TAG_LEN + extra_data_len;
}
/* Var-size header len includes len itself */
int2store(buf + RW_VHLEN_OFFSET, vhlen + vhpayloadlen);
rc= wrapper_my_b_safe_write(file, buf, ROWS_HEADER_LEN_V2);
/* Write var-sized payload, if any */
if ((vhpayloadlen > 0) &&
(rc == 0))
{
/* Add tag and extra row info */
uchar type_code= RW_V_EXTRAINFO_TAG;
rc= wrapper_my_b_safe_write(file, &type_code, RW_V_TAG_LEN);
if (rc==0)
rc= wrapper_my_b_safe_write(file, m_extra_row_data, extra_data_len);
}
}
else
{
rc= wrapper_my_b_safe_write(file, buf, ROWS_HEADER_LEN_V1);
}
可以看到實際上寫入的就是
uint16 vhlen= 2;
uint16 vhpayloadlen= 0;
有興趣可以參考原始碼:
Rows_log_event::write_data_header(IO_CACHE *file)
--variable data part
packed integer:表中欄位個數,這個地方為packed integer自行參考原始碼
uchar *net_store_length
var-size:文件解釋為每一位代表是否欄位用到了 長度為INT((n+7)/8) n代表欄位數量
原始碼描述為 m_cols; /* Bitmap denoting columns available */
測試表現這一位元組和binlog_row_image設定有關,預設為FULL每一個位元組始終為
0XFF
var-size:每一位代表的欄位的值是否為NULL,長度為INT((n+7)/8) n代表欄位數量,
他採用一個點陣圖的方式。
1:NULL
0:NOT NULL
var-size:這部分就是真正的資料了。
為了驗證我做了如下的測試表:
mysql> create table testnull2 (id int,name1 varchar(20),name2 varchar(20));
Query OK, 0 rows affected (0.09 sec)
mysql> insert into testnull2 values(NULL,'test',NULL);
Query OK, 1 row affected (0.01 sec)
可以看到我只是插入的資料第一個欄位第三個欄位都是NULL,好我們看是解析,這次試用
mysqlbinlog 自帶的--hexdump方式和自己開發的工具./infobin,這個工具就是透過自己
對binlog event的認知進行解析的,做這個工具的目的在於簡化和友好的輸出,方便我以後
的測試使用,同時也驗證了我的全部說法,有時候mysqlbinlog的輸出有點過於繁多,不便於
描述和測試,關於XID_EVENT和GTID_EVENT在後面描述
關於工具我放到了百度雲盤
[root@testmy data]# ./infobin test.000183
Check is Little_endian
Author: gaopeng QQ:22389860 Mail: gaopp_200217@163.com
Waring: This tool only Little_endian platform!
Little_endian check ok!!!
-------------Now begin--------------
Check Mysql Version is:5.7.13-log
Check Mysql binlog format ver is:V4
------------Detail now--------------
>Gtid Event:Pos:194(0Xc2) N_pos:259(0X103) Time:1486946663 Event_size:65(bytes)
Gtid:4a6f2a67-5d87-11e6-a6bd-0c29a879a3:1000448
-->Query Event:Pos:259(0X103) N_Pos:400(0X190) Time:1486946663 Event_size:141(bytes)
Exe_time:0 Use_db:test Statment(35b-trun):create table testnull2 (id int,name
>Gtid Event:Pos:400(0X190) N_pos:465(0X1d1) Time:1486946680 Event_size:65(bytes)
Gtid:4a6f2a67-5d87-11e6-a6bd-0c29a879a3:1000449
-->Query Event:Pos:465(0X1d1) N_Pos:537(0X219) Time:1486946680 Event_size:72(bytes)
Exe_time:0 Use_db:test Statment(35b-trun):BEGIN
---->Map Event:Pos537(0X219) N_pos:595(0X253) Time:1486946680 Event_size:58(bytes)
TABLE_ID:210 DB_NAME:test TABLE_NAME:testnull2
------>Insert Event:Pos:595(0X253) N_pos:636(0X27c) Time:1486946680 Event_size:41(bytes)
Dml on table: test.testnull2 table_id:210 Gno:1000449
>Xid Event:Pos:636(0X27c) N_Pos:667(0X29b) Time:1486946680 Event_size:31(bytes)
COMMIT 1000449 /*!add by tool*/
這裡找到了insert event:
------>Insert Event:Pos:595(0X253) N_pos:636(0X27c) Time:1486946680 Event_size:41(bytes)
Dml on table: test.testnull2 Gno:1000449
這裡這個event的開始位置為595
進行使用mysqlbinlog --hexdump格式
# at 595
#170213 8:44:40 server id 93157 end_log_pos 636 CRC32 0x32dd470a
# Position Timestamp Type Master ID Size Master Pos Flags
# 253 78 01 a1 58 1e e5 6b 01 00 29 00 00 00 7c 02 00 00 00 00
# 266 d2 00 00 00 00 00 01 00 02 00 03 ff fd 04 74 65 |..............te|
# 276 73 74 0a 47 dd 32 |st.G.2|
# Write_rows: table id 210 flags: STMT_END_F
下面是-vv的輸出
### INSERT INTO `test`.`testnull2`
### SET
### @1=NULL /* type=3 meta=0 nullable=1 is_null=1 */
### @2='test' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */
### @3=NULL /* VARSTRING(60) meta=60 nullable=1 is_null=1 */
分解:
--event header 部分就不解析了table id 210,
--hexdump也明確的解析了,不理解參考前面的文章
# Position Timestamp Type Master ID Size Master Pos Flags
# 253 78 01 a1 58 1e e5 6b 01 00 29 00 00 00 7c 02 00 00 00 00
--fixed data
d2 00 00 00 00 00:表ID就是./infobin中的TABLE_ID:210 也是mysqlbinlog中的Write_rows: table id 210
01 00:保留
02 00:m_extra_row_data,這部分是我看原始碼找到的。
--variable data part
03:表中欄位個數,當然我建表就是3個欄位
ff: 原始碼描述為 m_cols; /* Bitmap denoting columns available */
fd: 11111101 代表欄位@1=NULL和@3=NULL,但是欄位@2不為空這和mysqlbinlog解析的一致
@1=NULL /* type=3 meta=0 nullable=1 is_null=1 */
@2='test' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */
@3=NULL /* VARSTRING(60) meta=60 nullable=1 is_null=1 */
04:var 長度04 就是資料'test'的長度為4,當然為4
74 65 73 74:字串'test'
ca 3f c1 05:crc 32校驗
到此為止WRITE_ROW_EVENT解析完畢
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7728585/viewspace-2133463/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 解析MYSQL BINLOG二進位制格式(9)--infobin解析binlog幫助文件MySql
- 解析MYSQL BINLOG二進位制格式(10)--問題解答MySql
- 解析MYSQL BINLOG 二進位制格式(1)--準備工作MySql
- 解析MYSQL BINLOG 二進位制格式(3)--QUERY_EVENTMySql
- 解析MYSQL BINLOG 二進位制格式(4)--TABLE_MAP_EVENTMySql
- 解析MYSQL BINLOG 二進位制格式(2)--FORMAT_DESCRIPTION_EVENTMySqlORM
- 解析MYSQL BINLOG 二進位制格式(6)--UPDATE_ROW_EVENT/DELETE_ROW_EVENTMySqldelete
- MySQL二進位制檔案(binlog)MySql
- 解析MYSQL BINLOG 二進位制格式(7)--Xid_log_event/XID_EVENTMySql
- Java二進位制Class檔案格式解析Java
- 解析MYSQL BINLOG二進位制格式(8)--GTID_LOG_EVENT/ANONYMOUS_GTID_LOG_EVENT及其他MySql
- 二進位制求5個1的格式。。。。
- mysql二進位制日誌格式介紹MySql
- 如何在MySQL中檢視binlog二進位制日誌?MySql
- office檔案格式複合文件二進位制結構解析
- MySQL二進位制日誌MySql
- mysql 二進位制日誌MySql
- mixed模式下的binlog二進位制日誌解析,需要加-v引數模式
- C++資料格式化5 - uint轉換成十六進位制字串&二進位制的data列印成十六進位制字串C++UI字串
- Mysql二進位制包安裝MySql
- 管理mysql二進位制日誌MySql
- mysql的二進位制日誌MySql
- 二進位制與二進位制運算
- 進位制詳解:二進位制、八進位制和十六進位制
- [MySQL binlog]徹底解析Mixed日誌格式的binlogMySql
- JavaScript 二進位制、八進位制與十六進位制JavaScript
- MySQL二進位制日誌的三種格式優缺點比較MySql
- MySQL 壓縮二進位制日誌MySql
- mysql二進位制日誌詳解MySql
- MySQL linux二進位制安裝MySqlLinux
- mysql 二進位制日誌總結MySql
- 利用vstruct解析二進位制資料Struct
- (二進位制)
- 二進位制
- 十進位制——二 (八、十六 )進位制
- 二進位制,八進位制,十進位制,十六進位制的相互轉換
- 【進位制轉換】二進位制、十六進位制、十進位制、八進位制對應關係
- 二進位制、十進位制與十六進位制相互轉化