mysql client和server端之間的的數據根據不同的協議規則的進行組織發送。每包數據在發送的時候都要添加上協議頭。
mysql源碼采用5.7.10版本:
協議頭:
每個協議頭共4個字節
包數據長度:
前三個字節表示數據部分的長度(不包括協議頭),三字節能表示的最大長度是16M-1(2^24 - 1),如果要發送的數據部分大於這個長度,要進行拆包,每16M-1個長度為一包。接收端在接受數據的時候,如果檢測到包的長度是16M-1,說明后續還有數據部分,直到接收到<16M-1長度的數據包結束。這意味着最后一包的數據長度可能為0.
序號:
1個字節,從0開始遞增。當發送一個新的sql、數據庫重連,該值清0(函數sql/Net_serv.cc : net_clear).
數據類型:
除了固定長度的整型或者字符串之外,還有其他幾種類型的數據。(固定長度字段數據的存取:include/Mybyte_order.h : 存值 int*store 取值:int*korr 多字節的處理按照小端優先的方式)
1. 可變長度的整數
對該類數據的存取在函數:sql-common/Pack.c: 存整數: net_store_length 讀整數:net_field_length
如果數值<251,直接用一個字節存儲這個值。
如果251<=數值<2^16, 采用3個字節存儲,第一個字節是252, 另外2個字節存儲整數內容
如果2^16<=數值<2^24,采用4字節存儲,第一個字節是252,另外3個字節存儲整數內容
如果2^24<=數值<2^64,采用9字節存儲,第一個字節255,另外8字節存儲整數內容
如果第一個字節為251,表示該整數字段為null
如果第一個字節為255,表示該字節是ERR包的第一個字節
2. 可編碼長度的字符串
字符串的長度采用可變長度的整數進行編碼。
數據長度不固定,長度值由數據前的1-9個字節決定,其中長度值所占的字節數不定,字節數由第1個字節決定,如下表:
第一個字節值 | 后續字節數 | 長度值說明 |
---|---|---|
0-250 | 0 | 第一個字節值即為數據的真實長度 |
251 | 0 | 空數據,數據的真實長度為零 |
252 | 2 | 后續額外2個字節標識了數據的真實長度 |
253 | 3 | 后續額外3個字節標識了數據的真實長度 |
254 | 8 | 后續額外8個字節標識了數據的真實長度 |
3. null結尾的字符串
服務器響應包:
服務器響應包分為4類: OK包 ERR包 EOF包 數據包
OK包:在5.7.5之前,ok包首字節為0,;在5.7.5之后,ok包的首字節可能為0xFE,表示EOF。
該包包括成功執行后影響的行數,最新的自增id, 告警信息(4.1版本之上),服務器狀態信息:status_flag(該字段要留意,后續后講到)
執行函數:sql/protocol_classic.cc : net_send_ok
由於協議的內容容易變更,建議查看官網的最新版格式:https://dev.mysql.com/doc/internals/en/packet-OK_Packet.html
ERR包:首字節是255,報錯錯誤碼和錯誤的描述信息。4.1版本之上包括錯誤狀態。
執行函數:sql/protocol_classic.cc : net_send_error_packet
具體包格式:https://dev.mysql.com/doc/internals/en/packet-ERR_Packet.html
EOF包:首字節254,包括服務器狀態和告警數量(4.1版本之上)
執行函數:sql/protocol_classic.cc : net_send_eof
具體包格式:https://dev.mysql.com/doc/internals/en/packet-EOF_Packet.html
數據包:和具體的協議類型有關,后續講解