1. 程式人生 > 其它 >MySQL原始碼分析之 通訊協議(一)

MySQL原始碼分析之 通訊協議(一)

MySQL原始碼分析之 通訊協議(一)

mysql 通訊協議用於 mysql 客戶端和伺服器之間的通訊,通過以下幾種方式實現:

 1)、介面: (Connector/C, Connector/J, 等) 即平時我們所說的 JDBC ODBC 等介面

 2)、mysql 中介軟體

 3)、主伺服器和從伺服器之間的通訊

mysql 協議支援一下幾點功能:

 1)、使用 SSL 的透明加密

 2)、透明壓縮

 3)、連線階段,進行身份驗證和資料交換的能力

 4)、執行階段,接收客戶端發來的命令並執行他們

互動過程:

MySQL客戶端與伺服器的互動主要分為兩個階段:握手認證階段和命令執行階段。

握手認證階段為客戶端與伺服器建立連線後進行,互動過程如下:

  • 伺服器 -> 客戶端:握手初始化訊息
  • 客戶端 -> 伺服器:登陸認證訊息
  • 伺服器 -> 客戶端:認證結果訊息

客戶端認證成功後,會進入命令執行階段,互動過程如下:

  • 客戶端 -> 伺服器:執行命令訊息
  • 伺服器 -> 客戶端:命令執行結果

MySQL客戶端與伺服器的完整互動過程如下

基本型別:

1、整型

整型分為固定長度的整型和可變長度的整型(變長在這裡指的是儲存長度)。

固定長度型別屬於無符號整型,分別有1、2、3、4、6、8位元組長度,使用小位元組序傳輸最低有效位元組排在第一位。以3位元組長度整型為例可以檢視 int3store()

變長整型,可能佔用1、3、4、9個位元組,具體取決於其數值。把一個整型值轉換為一個可變位元組長度儲存需要如下操作:

因此,如果需要將變長儲存的整型轉化為數值,需要檢查第一個位元組。

注意: 如果資料包的第一個位元組是長度編碼的整數,其位元組值為0xFE,則必須檢查資料包的長度,以驗證其是否有足夠的空間容納8位元組整數。如果不是,它可能是一個EOF資料包。 

2、字串

字串在協議中有以下幾種形勢:

1)、固定長度的字串,具有已知的硬編碼長度。例如,ERR資料包的sql狀態總是5位元組長

2)、字串長度不固定,當遇到'NULL'(0x00)字元時結束。

3)、字串的長度由另一個欄位確定,或在執行時計算

4)、長度編碼字串,字串長度不固定,無'NULL'(0x00)結束符,編碼方式與上面的 Length Coded integer 相同

5)、如果字串是資料包的最後一個組成部分,則可以從資料包的總長度減去當前位置來計算其長度。

報文結構: 如果 MySQL 客戶端和伺服器想傳送資料,需要將資料拆為2**24大小的資料包(即16M)因此客戶端和伺服器之間以最大16M 的資料包進行交換。會為每個資料塊預先新增一個數據包頭。因此可以這麼理解:報文分為訊息頭和訊息體兩部分,其中訊息頭佔用固定的4個位元組,訊息體長度由訊息頭中的長度欄位決定,報文結構如下:

  

 1、訊息頭,記錄了報文長度:用於標記當前請求訊息的實際資料長度值,以位元組為單位,佔用3個位元組,最大值為 0xFFFFFF,即接近 16 MB 大小(比16MB少1個位元組)

 2、訊息頭,序列號,在一次完整的請求/響應互動過程中,用於保證訊息順序的正確,每次客戶端發起請求時,序號值都會從0開始計算。

 3、訊息體,訊息體用於存放請求的內容及響應的資料,長度由訊息頭中的長度值決定。

通用響應包(服務響應報文):

響應包可以分為三種,OK_Packet、 ERR_Packet、EOF_Packet。從MySQL 5.7.5開始,OK資料包也被用來表示EOF,EOF資料包被棄用。如果設定了CLIENT_PROTOCOL_41,即MySQL 版本大於4.1。 

該資料包包含一個警告計數。

1、OK 響應報文

客戶端的命令執行正確時,伺服器會返回OK響應報文。

如果 header = 0 並且packer 長度大於7,說明這個包是 OK 資料包

如果 header = 0xFE 並且 packer 長度小於9,說明這個包是 EOF 包。 

affecred rows:受影響行數,當執行 INSERT/UPDATE/DELETE 語句時所影響的資料行數

last_insert_id: 值為AUTO_INCREMENT索引欄位生成,如果沒有索引欄位,則為0x00。注意:當INSERT插入語句為多行資料時,該索引ID值為第一個插入的資料行索引值,而非最後一個

status_flags:  伺服器狀態,客戶端可以通過該值檢查命令是否在事務處理中

warnings:   告警次數,即告警發生的次數

session state info:  會話狀態資訊

info:  伺服器訊息,伺服器返回給客戶端的訊息,一般為簡單的描述性字串,可選欄位。

**會話狀態資訊**

狀態變化資訊作為一組狀態變化塊在OK資料包中傳送,這些狀態變化塊由以下部分組成:

型別:資料的型別,可以檢視 enum_session_state_type.。 資料,會話資訊改變的資料

enum enum_session_state_type {
  SESSION_TRACK_SYSTEM_VARIABLES, /**< Session system variables */
  SESSION_TRACK_SCHEMA,           /**< Current schema */
  SESSION_TRACK_STATE_CHANGE,     /**< track session state changes */
  SESSION_TRACK_GTIDS,            /**< See also: session_track_gtids */
  SESSION_TRACK_TRANSACTION_CHARACTERISTICS, /**< Transaction chistics */
  SESSION_TRACK_TRANSACTION_STATE            /**< Transaction state */
};

 資料欄位的解釋取決於型別值。

1)、SESSION_TRACK_SYSTEM_VARIABLES   會話跟蹤系統變數

2)、SESSION_TRACK_SCHEMA  會話跟蹤模式

3)、SESSION_TRACK_STATE_CHANGE 會話跟蹤狀態更改。 指示會話狀態是否發生更改的標誌位元組。此標誌表示為ASCII值

2、ERR 響應報文 

錯誤包意味著產生了錯誤資訊,在 MySQL4.1版本之後,它包含一個 SQL 狀態值,錯誤文字大小不能超過 Error texts cannot exceed。 程式碼函式 net_send_error_packet()

header: 訊息頭,ERR 報文問 0xFF

error-code:  錯誤碼,定義在原始碼/include/mysqld_error.h標頭檔案中

sql_state_marker:  伺服器狀態標誌,恆為'#'字元

sql_sate: 伺服器狀態,伺服器將錯誤編號通過mysql_errno_to_sqlstate函式轉換為狀態值,狀態值由5位元組的ASCII字元組成,定義在原始碼/include/sql_state.h標頭檔案中

error_message: 錯誤資訊,錯誤訊息字串到達訊息尾時結束,長度可以由訊息頭中的長度值計算得出。訊息長度為0-512位元組

3、EOF 響應報文 

如果啟用了CLIENT_PROTOCOL_41,則EOF資料包包含警告計數和狀態標誌。

在 mysql 的通訊協議中,EOF 資料包和 OK 資料包是一樣的目的,用來標記一個查詢結果的結束。在 MySQL5.7因為 OK 資料包發生了更改(如會話狀態跟蹤),為了避免 EOF 資料發生重複更改,在 MySQL5.7.5之後棄用 OK 資料包。

EOF_資料包可能出現在可能出現Protocol::engthCodedInteger的地方。您必須檢查資料包長度是否小於9,以確保它是EOF_資料包。

warnings: 告警計數,伺服器告警數量,在所有資料都發送給客戶端後該值才有效。

status_flags: 狀態標誌位,包含類似SERVER_MORE_RESULTS_EXISTS這樣的標誌位。

:由於EOF值與其它Result Set結構共用1位元組,所以在收到報文後需要對EOF包的真實性進行校驗,校驗條件為:

  • 第1位元組值為0xFE
  • 包長度小於9位元組

未完待續。。。。