mysql交互協議是開發mysql周邊組件常用的協議,如JDBC,libmysql等等。
在此我們要認識到mysql交互協議其實是半雙工的交互協議,至於為什麼,這裡就先挖個小坑,以後再填。
在探討mysql交互協議的格式之前,我們要理清一個小問題,就是mysql交互協議會用到的基本數據類型。
1.整數類型
這裡的整數類型可以用來表示mysql數據類型中的整數類型、日期時間類型、DOUBLE、FLOAT類型、比特類型以及枚舉類型等等。
所有的mysql整數類型都是小端的,這是網絡數據的慣例。即對於16進制數0x12345678,在存儲時會變成0x78563412
那麼這裡的整數數據類型有:int<len>(其中len = 1,2,3,4,6,8)以及可變的整數類型int<lenenc>
(1)int<len>是固定長度為len字節的整數數據,如int<3>表示數字3的話,會以小端 0x030000表示。
(2)int<lenenc>是可變長度類型的整數,這種字符的長度可以是1, 3, 4, 9。
我們設要表示的數值是n
1)當 n < 251時,int<lenenc>會以int<1>表示。
2)當251 <= n < 2^16時,int<lenenc>會以0xfc + int<2>表示。
3)當2^16 <= n < 2^24時,int<lenenc>會以0xfd + int<3>表示。
4)當2^24 <= n < 2^64時,int<lenenc>會以0xfe + int<8>表示。
這就表示如果我們遇到int<lenenc>類型,我們需要先讀取第一個數值type來判斷
1)當type < 0xfb時,就認為讀取的數是type。
2)當type == 0xfc時,就讀取後面的int<2>,int<2>才是真實的數值。
3)當type == 0xfd時,就讀取後面的int<3>,int<3>才是真實的數值。
4)當type == 0xfe時,就讀取後面的int<8>,int<8>才是真實的數值。
那麼當type為0xff和0xfb是什麼?這邊挖坑在此以後再填。
可以劇透下的是:
0xff在mysql交互協議中一般代表某一個動作錯誤,
如發送一個插入命令失敗後會有這種回復出現。
而0xfb代表NULL,就是mysql插入值往往會是空值,指的就是NULL
2.字符串類型
這裡的字符串類型可以用來表示mysql的高精度小數類型、字符串類型、大比特類型以及大整數類型等等。
這裡的字符串類型主要是
(1)string<len>就是長度為len的字符串。
(2)string<NUL> 就是string+'0x00',這裡的'0x00'是作為結尾符的。
(3)string<lenenc>就是int<lenenc> +string,int<lenenc> 代表字符串的長度。
(4)string<EOF>就是在一個mysql交互包結尾處出現的字符串。換言之,這個字符串是一個mysql交互包的最後一個字符串。
(5)string<fix>和string<var>幾乎用不到。
3.mysql包基本格式
mysql包長度 int<3> mysql包序號 int<1> mysql包內容 string<len>
mysql包長度就是mysql包內容的長度,不把包頭即包長度和包序號計入mysql包長度中,一般是int<3>,如果超過長度2^24-1,mysql會進行分包,如2^24-1,分成下述兩個包。
0xfffffff 0x00 mysql包內容 0x000000 0x01 mysql包內容
mysql包序號就是一個完整流程的發包序號,就是由該流程的發出的第一包是從0x00開始的,以後不管回復的包還是分包的包都會在上面加1,直到包序號達到0xff,再從0x001開始計數。
比如我要查詢語句"select * from 某表",那麼我會發送出第一個包含查詢語句"select * from 某表"的mysql包給mysql數據庫,這個包的序號是0x00,這時,流程開始,以後的mysql數據庫回復的包都會從0x01開始計數,直到回復結束,這時,該流程就結束了。我要查詢新的語句就代表新的流程開始,mysql包序號計數重新從0x00開始。
參考網址 http://dev.mysql.com/doc/internals/en/describing-packets.html#type-string.var_len
http://dev.mysql.com/doc/internals/en/mysql-packet.html