mysql 協議分析


MYSQL Binlog協議分析

 

此處不討論建立連接,驗證和handshake的交互協議

Binlog協議

 

 

一個MYSQL 通信包由包頭包體組成

 

包體根據具體的交互協議有自身的組成結構, 在binlog消息體組成結構如下

+=====================================+

| event  | timestamp         0 : 4    |

| header +----------------------------+

|        | type_code         4 : 1    |

|        +----------------------------+

|        | server_id         5 : 4    |

|        +----------------------------+

|        | event_length      9 : 4    |

+=====================================+

| event  | fixed part       13 : y    |

| data   +----------------------------+

|        | variable part              |

+=====================================+

 

注意: 消息體里組成是包括2部分的,第一個字節是master發送給slave的errorcode, 第二個字節開始才是具體消息, 所以一個完整的MYSQL binlog通信包組成如下

 

 

 
   

 

 

 

 

 

 

一次binlog復制通信包含若干個binlog通信包

 

我們通過抓包工具抓取一次binlog復制來分析

 

 

 

我們在master里更新了一條數據, 產生了 41 這條通信數據, 里面包含了4個mysql binlog通信包

第一個binlog事件消息

頭3個字節 45 00 00就是消息長度, 注意,在mysql協議里,數值類型是用小序列來傳輸數據的(小序列: 低位先傳), 這條消息里實際消息長度內容是 00 00 45 , 也就是69(45是16進制, 69是10進制)

第4個字節2c是master傳過來的序號

第5個字節00時errorcode, 0表示沒有錯誤, 其他是錯誤

第6~9  4個字節是timestamp

第10 個字節02 是event type, 比如query, insert, update,delete等的類型碼

第11-14個字節是serverid, 這里是02 00 00 00, 也是小序列

第15~19個字節是eventlengthoffset, 這里是44 00 00 00, 也是小序列

第二個binlog事件消息

 

 

結構和第一個基本一樣, 只是消息長度,序號,eventtype等內容不一樣

 

以上是原生mysql復制binlog的交互協議情況, 如果開啟了semi半同步, 協議就發生變化, tcp通信次數, 包體結構等都和原來的有差異

抓包分析:

 

 

我們在master里更新了一條數據, 產生了 5 這條通信數據, 里面包含了5個mysql binlog通信包, 比原生的多了1條, 而且包結構也變成了以下結構

 

 

 
   

 

 

 

 

 

 

 

第一個binlog事件消息是新增的事件

 

 

第6個字節是新增的字節碼, ef是固定的值,表示這是個semi的消息

第7個字節是新增的字節碼, 0或者1, 0表示不需要回一個ack給master, 1表示需要, 一次復制通信(包含5個binlog事件)只有最后一個binlog事件的值為1

第8個字節開始就是具體消息, 和原生的一樣

 

最后一個binlog事件消息

 

第7個字節值是1 ,  表示要返回一個ack給master

 

以下就是ack給master的內容

 

 

Slave ack給master 的消息是7這條通信數據

第1-3個字節師消息長度,這里的內容是12 00 00, 十進制內容是18

第4個字節是序號 , 這里是0, (注意: 每次tcp交互里這個序號都被重至為0)

第5個字節是semi標示 ,固定為ef

第6~14個字節,一共8個字節表示位置offset, ef 0a 00 00 00 00 00 00 同樣是小序列

第15個字節開始是binlog的文件名 每個字節存儲的是ascii碼, 如這里的4f=O, 4e=N,2e=.,30=0,36=6, 就是ON.000006

 

 

如果安裝了semi插件后,並不啟用semi同步,就不會發送ack給master, 就是上面7這個數據包不會發送

 

 

Master要發送semi字節給slave前提是slave連接上master后必須發送SET @rpl_semi_sync_slave= 1 指令給master, 看下面抓包效果

 

 

1c 00 00 00 是包頭

0x03 是指令碼       COM_QUERY

53開始后面的字節都是具體字符串的ascii碼

 

 

完整事件流

Slave連接上master后, master 首先會發ROTATE_EVENT和FORMAT_DESCRIPTION_EVENT 2個事件給slave, ROTATE_EVENT事件告訴slave下一個要讀取的binlog(可以理解成初始化要讀取的binlog)

 

Master發生一個插入sql, 如insert into test1 values(15), 分別發送給slave的事件是ANONYMOUS_GTID_LOG_EVENT-->QUERY_EVENT-->TABLE_MAP_EVENT-->WRITE_ROWS_EVENT-->XID_EVENT

 

(1)

ANONYMOUS_GTID_LOG_EVENT

(2)

QUERY_EVENT

header {

  version: 1

  logfileName: "20170105-162017-bin.000001"

  logfileOffset: 1920

  serverId: 1

  serverenCode: "UTF-8"

  executeTime: 1508809530000

  sourceType: MYSQL

  schemaName: ""

  tableName: ""

  eventLength: 72

}

entryType: TRANSACTIONBEGIN

storeValue: " \354\001"

 

(3)

TABLE_MAP_EVENT

 

(4)

WRITE_ROWS_EVENT

header {

  version: 1

  logfileName: "20170105-162017-bin.000001"

  logfileOffset: 2040

  serverId: 1

  serverenCode: "UTF-8"

  executeTime: 1508809530000

  sourceType: MYSQL

  schemaName: "test"

  tableName: "test1"

  eventLength: 40

  eventType: INSERT

}

entryType: ROWDATA

storeValue: "\b\333\001\020\001P\000b\035\022\033\b\000\020\004\032\002id \000(\0010\000B\00215R\aint(11)"

 

(5)

XID_EVENT

header {

  version: 1

  logfileName: "20170105-162017-bin.000001"

  logfileOffset: 2080

  serverId: 1

  serverenCode: "UTF-8"

  executeTime: 1508809530000

  sourceType: MYSQL

  schemaName: ""

  tableName: ""

  eventLength: 31

}

entryType: TRANSACTIONEND

storeValue: "\022\003184"

 

 

 

 

PS:

如果本地沒有存儲position,在slave啟動的時候就會調用show master status 獲取master 最新的position更新到本地

 

在實驗中發現 master 的timeout時間設置很長, 當新日志送到canal, canal關閉,master由於收不到ack,一直hold着,再次啟動canal, master hold住的事務能夠進行下去,數據也落盤到master硬盤里,但再次啟動的canal就沒有收到之前中斷掉的binlog(開始position是master最后的position)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM