MySQL協議分析


目錄

  • 目錄
  • 1 交互過程
    • 1.1 握手認證階段
    • 1.2 命令執行階段
  • 2 基本類型
    • 2.1 整型值
    • 2.2 字符串(以NULL結尾)(Null-Terminated String)
    • 2.3 二進制數據(長度編碼)(Length Coded Binary)
    • 2.4 字符串(長度編碼)(Length Coded String)
  • 3 報文結構
    • 3.1 消息頭
      • 3.1.1 報文長度
      • 3.1.2 序號
    • 3.2 消息體
  • 4 報文類型
    • 4.1 登陸認證交互報文
      • 4.1.1 握手初始化報文(服務器 -> 客戶端)
      • 4.1.2 登陸認證報文(客戶端 -> 服務器)
    • 4.2 客戶端命令請求報文(客戶端 -> 服務器)
      • 4.2.1 COM_QUIT 消息報文
      • 4.2.2 COM_INIT_DB 消息報文
      • 4.2.3 COM_QUERY 消息報文
      • 4.2.4 COM_FIELD_LIST 消息報文
      • 4.2.5 COM_CREATE_DB 消息報文
      • 4.2.6 COM_DROP_DB 消息報文
      • 4.2.7 COM_REFRESH 消息報文
      • 4.2.8 COM_SHUTDOWN 消息報文
      • 4.2.9 COM_STATISTICS 消息報文
      • 4.2.10 COM_PROCESS_INFO 消息報文
      • 4.2.11 COM_PROCESS_KILL 消息報文
      • 4.2.12 COM_DEBUG 消息報文
      • 4.2.13 COM_PING 消息報文
      • 4.2.14 COM_CHANGE_USER 消息報文
      • 4.2.15 COM_BINLOG_DUMP 消息報文
      • 4.2.16 COM_TABLE_DUMP 消息報文
      • 4.2.17 COM_REGISTER_SLAVE 消息報文
      • 4.2.18 COM_PREPARE 消息報文
      • 4.2.19 COM_EXECUTE 消息報文
      • 4.2.20 COM_LONG_DATA 消息報文
      • 4.2.21 COM_CLOSE_STMT 消息報文
      • 4.2.22 COM_RESET_STMT 消息報文
      • 4.2.23 COM_SET_OPTION 消息報文
      • 4.2.24 COM_FETCH_STMT 消息報文
    • 4.3 服務器響應報文(服務器 -> 客戶端)
      • 4.3.1 OK 響應報文
      • 4.3.2 Error 響應報文
      • 4.3.3 Result Set 消息
      • 4.3.4 Result Set Header 結構
      • 4.3.5 Field 結構
      • 4.3.6 EOF 結構
      • 4.3.7 Row Data 結構
      • 4.3.8 Row Data 結構(二進制數據)
      • 4.3.9 PREPARE_OK 響應報文(Prepared Statement)
      • 4.3.10 Parameter 響應報文(Prepared Statement)
  • 5 參考資料

1 交互過程

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

1.1 握手認證階段

握手認證階段為客戶端與服務器建立連接后進行,交互過程如下:

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

1.2 命令執行階段

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

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

MySQL客戶端與服務器的完整交互過程如下

2 基本類型

2.1 整型值

MySQL報文中整型值分別有1、2、3、4、8字節長度,使用小字節序傳輸。

2.2 字符串(以NULL結尾)(Null-Terminated String)

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

2.3 二進制數據(長度編碼)(Length Coded Binary)

數據長度不固定,長度值由數據前的1-9個字節決定,其中長度值所占的字節數不定,字節數由第1個字節決定,如下表:

第一個字節值 后續字節數 長度值說明
0-250 0 第一個字節值即為數據的真實長度
251 0 空數據,數據的真實長度為零
252 2 后續額外2個字節標識了數據的真實長度
253 3 后續額外3個字節標識了數據的真實長度
254 8 后續額外8個字節標識了數據的真實長度

2.4 字符串(長度編碼)(Length Coded String)

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

3 報文結構

報文分為消息頭和消息體兩部分,其中消息頭占用固定的4個字節,消息體長度由消息頭中的長度字段決定,報文結構如下:

 

3.1 消息頭

3.1.1 報文長度

用於標記當前請求消息的實際數據長度值,以字節為單位,占用3個字節,最大值為 0xFFFFFF,即接近 16 MB 大小(比16MB少1個字節)。

3.1.2 序號

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

3.2 消息體

消息體用於存放請求的內容及響應的數據,長度由消息頭中的長度值決定。

4 報文類型

4.1 登陸認證交互報文

4.1.1 握手初始化報文(服務器 -> 客戶端)

服務協議版本號:該值由 PROTOCOL_VERSION 宏定義決定(參考MySQL源代碼/include/mysql_version.h頭文件定義)

服務版本信息:該值為字符串,由 MYSQL_SERVER_VERSION 宏定義決定(參考MySQL源代碼/include/mysql_version.h頭文件定義)

服務器線程ID:服務器為當前連接所創建的線程ID。

挑戰隨機數:MySQL數據庫用戶認證采用的是挑戰/應答的方式,服務器生成該挑戰數並發送給客戶端,由客戶端進行處理並返回相應結果,然后服務器檢查是否與預期的結果相同,從而完成用戶認證的過程。

服務器權能標志:用於與客戶端協商通訊方式,各標志位含義如下(參考MySQL源代碼/include/mysql_com.h中的宏定義):

標志位名稱 標志位 說明
CLIENT_LONG_PASSWORD 0x0001 new more secure passwords
CLIENT_FOUND_ROWS 0x0002 Found instead of affected rows
CLIENT_LONG_FLAG 0x0004 Get all column flags
CLIENT_CONNECT_WITH_DB 0x0008 One can specify db on connect
CLIENT_NO_SCHEMA 0x0010 Do not allow database.table.column
CLIENT_COMPRESS 0x0020 Can use compression protocol
CLIENT_ODBC 0x0040 Odbc client
CLIENT_LOCAL_FILES 0x0080 Can use LOAD DATA LOCAL
CLIENT_IGNORE_SPACE 0x0100 Ignore spaces before '('
CLIENT_PROTOCOL_41 0x0200 New 4.1 protocol
CLIENT_INTERACTIVE 0x0400 This is an interactive client
CLIENT_SSL 0x0800 Switch to SSL after handshake
CLIENT_IGNORE_SIGPIPE 0x1000 IGNORE sigpipes
CLIENT_TRANSACTIONS 0x2000 Client knows about transactions
CLIENT_RESERVED 0x4000 Old flag for 4.1 protocol
CLIENT_SECURE_CONNECTION 0x8000 New 4.1 authentication
CLIENT_MULTI_STATEMENTS 0x0001 0000 Enable/disable multi-stmt support
CLIENT_MULTI_RESULTS 0x0002 0000 Enable/disable multi-results

字符編碼:標識服務器所使用的字符集。

服務器狀態:狀態值定義如下(參考MySQL源代碼/include/mysql_com.h中的宏定義):

狀態名稱 狀態值
SERVER_STATUS_IN_TRANS 0x0001
SERVER_STATUS_AUTOCOMMIT 0x0002
SERVER_STATUS_CURSOR_EXISTS 0x0040
SERVER_STATUS_LAST_ROW_SENT 0x0080
SERVER_STATUS_DB_DROPPED 0x0100
SERVER_STATUS_NO_BACKSLASH_ESCAPES 0x0200
SERVER_STATUS_METADATA_CHANGED 0x0400

4.1.2 登陸認證報文(客戶端 -> 服務器)

 

客戶端權能標志:用於與客戶端協商通訊方式,標志位含義與握手初始化報文中的相同。客戶端收到服務器發來的初始化報文后,會對服務器發送的權能標志進行修改,保留自身所支持的功能,然后將權能標返回給服務器,從而保證服務器與客戶端通訊的兼容性。

最大消息長度:客戶端發送請求報文時所支持的最大消息長度值。

字符編碼:標識通訊過程中使用的字符編碼,與服務器在認證初始化報文中發送的相同。

用戶名:客戶端登陸用戶的用戶名稱。

挑戰認證數據:客戶端用戶密碼使用服務器發送的挑戰隨機數進行加密后,生成挑戰認證數據,然后返回給服務器,用於對用戶身份的認證。

數據庫名稱:當客戶端的權能標志位 CLIENT_CONNECT_WITH_DB 被置位時,該字段必須出現。

4.2 客戶端命令請求報文(客戶端 -> 服務器)

MySQL客戶端命令請求報文

命令:用於標識當前請求消息的類型,例如切換數據庫(0x02)、查詢命令(0x03)等。命令值的取值范圍及說明如下表(參考MySQL源代碼/include/mysql_com.h頭文件中的定義):

類型值 命令 功能 關聯函數
0x00 COM_SLEEP (內部線程狀態) (無)
0x01 COM_QUIT 關閉連接 mysql_close
0x02 COM_INIT_DB 切換數據庫 mysql_select_db
0x03 COM_QUERY SQL查詢請求 mysql_real_query
0x04 COM_FIELD_LIST 獲取數據表字段信息 mysql_list_fields
0x05 COM_CREATE_DB 創建數據庫 mysql_create_db
0x06 COM_DROP_DB 刪除數據庫 mysql_drop_db
0x07 COM_REFRESH 清除緩存 mysql_refresh
0x08 COM_SHUTDOWN 停止服務器 mysql_shutdown
0x09 COM_STATISTICS 獲取服務器統計信息 mysql_stat
0x0A COM_PROCESS_INFO 獲取當前連接的列表 mysql_list_processes
0x0B COM_CONNECT (內部線程狀態) (無)
0x0C COM_PROCESS_KILL 中斷某個連接 mysql_kill
0x0D COM_DEBUG 保存服務器調試信息 mysql_dump_debug_info
0x0E COM_PING 測試連通性 mysql_ping
0x0F COM_TIME (內部線程狀態) (無)
0x10 COM_DELAYED_INSERT (內部線程狀態) (無)
0x11 COM_CHANGE_USER 重新登陸(不斷連接) mysql_change_user
0x12 COM_BINLOG_DUMP 獲取二進制日志信息 (無)
0x13 COM_TABLE_DUMP 獲取數據表結構信息 (無)
0x14 COM_CONNECT_OUT (內部線程狀態) (無)
0x15 COM_REGISTER_SLAVE 從服務器向主服務器進行注冊 (無)
0x16 COM_STMT_PREPARE 預處理SQL語句 mysql_stmt_prepare
0x17 COM_STMT_EXECUTE 執行預處理語句 mysql_stmt_execute
0x18 COM_STMT_SEND_LONG_DATA 發送BLOB類型的數據 mysql_stmt_send_long_data
0x19 COM_STMT_CLOSE 銷毀預處理語句 mysql_stmt_close
0x1A COM_STMT_RESET 清除預處理語句參數緩存 mysql_stmt_reset
0x1B COM_SET_OPTION 設置語句選項 mysql_set_server_option
0x1C COM_STMT_FETCH 獲取預處理語句的執行結果 mysql_stmt_fetch

參數:內容是用戶在MySQL客戶端輸入的命令(不包括每行命令結尾的";"分號)。另外這個字段的字符串不是以NULL字符結尾,而是通過消息頭中的長度值計算而來。

例如:當我們在MySQL客戶端中執行use hutaow;命令時(切換到hutaow數據庫),發送的請求報文數據會是下面的樣子:

0x02 0x68 0x75 0x74 0x61 0x6f 0x77

其中,0x02為請求類型值COM_INIT_DB,后面的0x68 0x75 0x74 0x61 0x6f 0x77為ASCII字符hutaow

4.2.1 COM_QUIT 消息報文

功能:關閉當前連接(客戶端退出),無參數。

4.2.2 COM_INIT_DB 消息報文

功能:切換數據庫,對應的SQL語句為USE <database>

字節 說明
n 數據庫名稱(字符串到達消息尾部時結束,無結束符)

4.2.3 COM_QUERY 消息報文

功能:最常見的請求消息類型,當用戶執行SQL語句時發送該消息。

字節 說明
n SQL語句(字符串到達消息尾部時結束,無結束符)

4.2.4 COM_FIELD_LIST 消息報文

功能:查詢某表的字段(列)信息,等同於SQL語句SHOW [FULL] FIELDS FROM ...

字節 說明
n 表格名稱(Null-Terminated String)
n 字段(列)名稱或通配符(可選)

4.2.5 COM_CREATE_DB 消息報文

功能:創建數據庫,該消息已過時,而被SQL語句CREATE DATABASE代替。

字節 說明
n 數據庫名稱(字符串到達消息尾部時結束,無結束符)

4.2.6 COM_DROP_DB 消息報文

功能:刪除數據庫,該消息已過時,而被SQL語句DROP DATABASE代替。

字節 說明
n 數據庫名稱(字符串到達消息尾部時結束,無結束符)

4.2.7 COM_REFRESH 消息報文

功能:清除緩存,等同於SQL語句FLUSH,或是執行mysqladmin flush-foo命令時發送該消息。

字節 說明
1 清除緩存選項(位圖方式存儲,各標志位含義如下)
  0x01: REFRESH_GRANT
  0x02: REFRESH_LOG
  0x04: REFRESH_TABLES
  0x08: REFRESH_HOSTS
  0x10: REFRESH_STATUS
  0x20: REFRESH_THREADS
  0x40: REFRESH_SLAVE
  0x80: REFRESH_MASTER

4.2.8 COM_SHUTDOWN 消息報文

功能:停止MySQL服務。執行mysqladmin shutdown命令時發送該消息。

字節 說明
1 停止服務選項
  0x00: SHUTDOWN_DEFAULT
  0x01: SHUTDOWN_WAIT_CONNECTIONS
  0x02: SHUTDOWN_WAIT_TRANSACTIONS
  0x08: SHUTDOWN_WAIT_UPDATES
  0x10: SHUTDOWN_WAIT_ALL_BUFFERS
  0x11: SHUTDOWN_WAIT_CRITICAL_BUFFERS
  0xFE: KILL_QUERY
  0xFF: KILL_CONNECTION

4.2.9 COM_STATISTICS 消息報文

功能:查看MySQL服務的統計信息(例如運行時間、每秒查詢次數等)。執行mysqladmin status命令時發送該消息,無參數。

4.2.10 COM_PROCESS_INFO 消息報文

功能:獲取當前活動的線程(連接)列表。等同於SQL語句SHOW PROCESSLIST,或是執行mysqladmin processlist命令時發送該消息,無參數。

4.2.11 COM_PROCESS_KILL 消息報文

功能:要求服務器中斷某個連接。等同於SQL語句KILL <id>

字節 說明
4 連接ID號(小字節序)

4.2.12 COM_DEBUG 消息報文

功能:要求服務器將調試信息保存下來,保存的信息多少依賴於編譯選項設置(debug=no|yes|full)。執行mysqladmin debug命令時發送該消息,無參數。

4.2.13 COM_PING 消息報文

功能:該消息用來測試連通性,同時會將服務器的無效連接(超時)計數器清零。執行mysqladmin ping命令時發送該消息,無參數。

4.2.14 COM_CHANGE_USER 消息報文

功能:在不斷連接的情況下重新登陸,該操作會銷毀MySQL服務器端的會話上下文(包括臨時表、會話變量等)。有些連接池用這種方法實現清除會話上下文。

字節 說明
n 用戶名(字符串以NULL結尾)
n 密碼(挑戰數)
  MySQL 3.23 版本:Null-Terminated String(長度9字節)
  MySQL 4.1 版本:Length Coded String(長度1+21字節)
n 數據庫名稱(Null-Terminated String)
2 字符編碼

4.2.15 COM_BINLOG_DUMP 消息報文

功能:該消息是備份連接時由從服務器向主服務器發送的最后一個請求,主服務器收到后,會響應一系列的報文,每個報文都包含一個二進制日志事件。如果主服務器出現故障時,會發送一個EOF報文。

字節 說明
4 二進制日志數據的起始位置(小字節序)
4 二進制日志數據標志位(目前未使用,永遠為0x00)
4 從服務器的服務器ID值(小字節序)
n 二進制日志的文件名稱(可選,默認值為主服務器上第一個有效的文件名)

4.2.16 COM_TABLE_DUMP 消息報文

功能:將數據表從主服務器復制到從服務器中,執行SQL語句LOAD TABLE ... FROM MASTER時發送該消息。目前該消息已過時,不再使用。

字節 說明
n 數據庫名稱(Length Coded String)
n 數據表名稱(Length Coded String)

4.2.17 COM_REGISTER_SLAVE 消息報文

功能:在從服務器report_host變量設置的情況下,當備份連接時向主服務器發送的注冊消息。

字節 說明
4 從服務器ID值(小字節序)
n 主服務器IP地址(Length Coded String)
n 主服務器用戶名(Length Coded String)
n 主服務器密碼(Length Coded String)
2 主服務器端口號
4 安全備份級別(由MySQL服務器rpl_recovery_rank變量設置,暫時未使用)
4 主服務器ID值(值恆為0x00)

4.2.18 COM_PREPARE 消息報文

功能:預處理SQL語句,使用帶有"?"占位符的SQL語句時發送該消息。

字節 說明
n 帶有"?"占位符的SQL語句(字符串到達消息尾部時結束,無結束符)

4.2.19 COM_EXECUTE 消息報文

功能:執行預處理語句。

字節 說明
4 預處理語句的ID值
1 標志位
  0x00: CURSOR_TYPE_NO_CURSOR
  0x01: CURSOR_TYPE_READ_ONLY
  0x02: CURSOR_TYPE_FOR_UPDATE
  0x04: CURSOR_TYPE_SCROLLABLE
4 保留(值恆為0x01)
如果參數數量大於0  
n 空位圖(Null-Bitmap,長度 = (參數數量 + 7) / 8 字節)
1 參數分隔標志
如果參數分隔標志值為1  
n 每個參數的類型值(長度 = 參數數量 * 2 字節)
n 每個參數的值

4.2.20 COM_LONG_DATA 消息報文

該消息報文有兩種形式,一種用於發送二進制數據,另一種用於發送文本數據。

功能:用於發送二進制(BLOB)類型的數據(調用mysql_stmt_send_long_data函數)。

字節 說明
4 預處理語句的ID值(小字節序)
2 參數序號(小字節序)
n 數據負載(數據到達消息尾部時結束,無結束符)

功能:用於發送超長字符串類型的數據(調用mysql_send_long_data函數)

字節 說明
4 預處理語句的ID值(小字節序)
2 參數序號(小字節序)
2 數據類型(未使用)
n 數據負載(數據到達消息尾部時結束,無結束符)

4.2.21 COM_CLOSE_STMT 消息報文

功能:銷毀預處理語句。

字節 說明
4 預處理語句的ID值(小字節序)

4.2.22 COM_RESET_STMT 消息報文

功能:將預處理語句的參數緩存清空。多數情況和COM_LONG_DATA一起使用。

字節 說明
4 預處理語句的ID值(小字節序)

4.2.23 COM_SET_OPTION 消息報文

功能:設置語句選項,選項值為/include/mysql_com.h頭文件中定義的enum_mysql_set_option枚舉類型:

  • MYSQL_OPTION_MULTI_STATEMENTS_ON
  • MYSQL_OPTION_MULTI_STATEMENTS_OFF
字節 說明
2 選項值(小字節序)

4.2.24 COM_FETCH_STMT 消息報文

功能:獲取預處理語句的執行結果(一次可以獲取多行數據)。

字節 說明
4 預處理語句的ID值(小字節序)
4 數據的行數(小字節序)

4.3 服務器響應報文(服務器 -> 客戶端)

當客戶端發起認證請求或命令請求后,服務器會返回相應的執行結果給客戶端。客戶端在收到響應報文后,需要首先檢查第1個字節的值,來區分響應報文的類型。

響應報文類型 第1個字節取值范圍
OK 響應報文 0x00
Error 響應報文 0xFF
Result Set 報文 0x01 - 0xFA
Field 報文 0x01 - 0xFA
Row Data 報文 0x01 - 0xFA
EOF 報文 0xFE

注:響應報文的第1個字節在不同類型中含義不同,比如在OK報文中,該字節並沒有實際意義,值恆為0x00;而在Result Set報文中,該字節又是長度編碼的二進制數據結構(Length Coded Binary)中的第1字節。

4.3.1 OK 響應報文

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

MySQL 4.0 及之前的版本

字節 說明
1 OK報文,值恆為0x00
1-9 受影響行數(Length Coded Binary)
1-9 索引ID值(Length Coded Binary)
2 服務器狀態
n 服務器消息(字符串到達消息尾部時結束,無結束符)

MySQL 4.1 及之后的版本

字節 說明
1 OK報文,值恆為0x00
1-9 受影響行數(Length Coded Binary)
1-9 索引ID值(Length Coded Binary)
2 服務器狀態
2 告警計數
n 服務器消息(字符串到達消息尾部時結束,無結束符,可選)

受影響行數:當執行INSERT/UPDATE/DELETE語句時所影響的數據行數。

索引ID值:該值為AUTO_INCREMENT索引字段生成,如果沒有索引字段,則為0x00。注意:當INSERT插入語句為多行數據時,該索引ID值為第一個插入的數據行索引值,而非最后一個。

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

告警計數:告警發生的次數。

服務器消息:服務器返回給客戶端的消息,一般為簡單的描述性字符串,可選字段。

4.3.2 Error 響應報文

MySQL 4.0 及之前的版本

字節 說明
1 Error報文,值恆為0xFF
2 錯誤編號(小字節序)
n 服務器消息

MySQL 4.1 及之后的版本

字節 說明
1 Error報文,值恆為0xFF
2 錯誤編號(小字節序)
1 服務器狀態標志,恆為'#'字符
5 服務器狀態(5個字符)
n 服務器消息

錯誤編號:錯誤編號值定義在源代碼/include/mysqld_error.h頭文件中。

服務器狀態:服務器將錯誤編號通過mysql_errno_to_sqlstate函數轉換為狀態值,狀態值由5字節的ASCII字符組成,定義在源代碼/include/sql_state.h頭文件中。

服務器消息:錯誤消息字符串到達消息尾時結束,長度可以由消息頭中的長度值計算得出。消息長度為0-512字節。

4.3.3 Result Set 消息

當客戶端發送查詢請求后,在沒有錯誤的情況下,服務器會返回結果集(Result Set)給客戶端。

Result Set 消息分為五部分,結構如下:

結構 說明
[Result Set Header] 列數量
[Field] 列信息(多個)
[EOF] 列結束
[Row Data] 行數據(多個)
[EOF] 數據結束

4.3.4 Result Set Header 結構

字節 說明
1-9 Field結構計數(Length Coded Binary)
1-9 額外信息(Length Coded Binary)

Field結構計數:用於標識Field結構的數量,取值范圍0x00-0xFA。

額外信息:可選字段,一般情況下不應該出現。只有像SHOW COLUMNS這種語句的執行結果才會用到額外信息(標識表格的列數量)。

4.3.5 Field 結構

Field為數據表的列信息,在Result Set中,Field會連續出現多次,次數由Result Set Header結構中的IField結構計數值決定。

MySQL 4.0 及之前的版本

字節 說明
n 數據表名稱(Length Coded String)
n 列(字段)名稱(Length Coded String)
4 列(字段)長度(Length Coded String)
2 列(字段)類型(Length Coded String)
2 列(字段)標志(Length Coded String)
1 整型值精度
n 默認值(Length Coded String)

MySQL 4.1 及之后的版本

字節 說明
n 目錄名稱(Length Coded String)
n 數據庫名稱(Length Coded String)
n 數據表名稱(Length Coded String)
n 數據表原始名稱(Length Coded String)
n 列(字段)名稱(Length Coded String)
4 列(字段)原始名稱(Length Coded String)
1 填充值
2 字符編碼
4 列(字段)長度
1 列(字段)類型
2 列(字段)標志
1 整型值精度
2 填充值(0x00)
n 默認值(Length Coded String)

目錄名稱:在4.1及之后的版本中,該字段值為"def"。

數據庫名稱:數據庫名稱標識。

數據表名稱:數據表的別名(AS之后的名稱)。

數據表原始名稱:數據表的原始名稱(AS之前的名稱)。

列(字段)名稱:列(字段)的別名(AS之后的名稱)。

列(字段)原始名稱:列(字段)的原始名稱(AS之前的名稱)。

字符編碼:列(字段)的字符編碼值。

列(字段)長度:列(字段)的長度值,真實長度可能小於該值,例如VARCHAR(2)類型的字段實際只能存儲1個字符。

列(字段)類型:列(字段)的類型值,取值范圍如下(參考源代碼/include/mysql_com.h頭文件中的enum_field_type枚舉類型定義):

類型值 名稱
0x00 FIELD_TYPE_DECIMAL
0x01 FIELD_TYPE_TINY
0x02 FIELD_TYPE_SHORT
0x03 FIELD_TYPE_LONG
0x04 FIELD_TYPE_FLOAT
0x05 FIELD_TYPE_DOUBLE
0x06 FIELD_TYPE_NULL
0x07 FIELD_TYPE_TIMESTAMP
0x08 FIELD_TYPE_LONGLONG
0x09 FIELD_TYPE_INT24
0x0A FIELD_TYPE_DATE
0x0B FIELD_TYPE_TIME
0x0C FIELD_TYPE_DATETIME
0x0D FIELD_TYPE_YEAR
0x0E FIELD_TYPE_NEWDATE
0x0F FIELD_TYPE_VARCHAR (new in MySQL 5.0)
0x10 FIELD_TYPE_BIT (new in MySQL 5.0)
0xF6 FIELD_TYPE_NEWDECIMAL (new in MYSQL 5.0)
0xF7 FIELD_TYPE_ENUM
0xF8 FIELD_TYPE_SET
0xF9 FIELD_TYPE_TINY_BLOB
0xFA FIELD_TYPE_MEDIUM_BLOB
0xFB FIELD_TYPE_LONG_BLOB
0xFC FIELD_TYPE_BLOB
0xFD FIELD_TYPE_VAR_STRING
0xFE FIELD_TYPE_STRING
0xFF FIELD_TYPE_GEOMETRY

列(字段)標志:各標志位定義如下(參考源代碼/include/mysql_com.h頭文件中的宏定義):

標志位 名稱
0x0001 NOT_NULL_FLAG
0x0002 PRI_KEY_FLAG
0x0004 UNIQUE_KEY_FLAG
0x0008 MULTIPLE_KEY_FLAG
0x0010 BLOB_FLAG
0x0020 UNSIGNED_FLAG
0x0040 ZEROFILL_FLAG
0x0080 BINARY_FLAG
0x0100 ENUM_FLAG
0x0200 AUTO_INCREMENT_FLAG
0x0400 TIMESTAMP_FLAG
0x0800 SET_FLAG

數值精度:該字段對DECIMALNUMERIC類型的數值字段有效,用於標識數值的精度(小數點位置)。

默認值:該字段用在數據表定義中,普通的查詢結果中不會出現。

:Field結構的相關處理函數:

  • 客戶端:/client/client.c源文件中的unpack_fields函數
  • 服務器:/sql/sql_base.cc源文件中的send_fields函數

4.3.6 EOF 結構

EOF結構用於標識Field和Row Data的結束,在預處理語句中,EOF也被用來標識參數的結束。

MySQL 4.0 及之前的版本

字節 說明
1 EOF值(0xFE)

MySQL 4.1 及之后的版本

字節 說明
1 EOF值(0xFE)
2 告警計數
2 狀態標志位

告警計數:服務器告警數量,在所有數據都發送給客戶端后該值才有效。

狀態標志位:包含類似SERVER_MORE_RESULTS_EXISTS這樣的標志位。

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

  • 第1字節值為0xFE
  • 包長度小於9字節

:EOF結構的相關處理函數:

  • 服務器:protocol.cc源文件中的send_eof函數

4.3.7 Row Data 結構

在Result Set消息中,會包含多個Row Data結構,每個Row Data結構又包含多個字段值,這些字段值組成一行數據。

字節 說明
n 字段值(Length Coded String)
... (一行數據中包含多個字段值)

字段值:行數據中的字段值,字符串形式。

:Row Data結構的相關處理函數:

  • 客戶端:/client/client.c源文件中的read_rows函數

4.3.8 Row Data 結構(二進制數據)

該結構用於傳輸二進制的字段值,既可以是服務器返回的結果,也可以是由客戶端發送的(當執行預處理語句時,客戶端使用Result Set消息來發送參數及數據)。

字節 說明
1 結構頭(0x00)
(列數量 + 7 + 2) / 8 空位圖
n 字段值
... (一行數據中包含多個字段值)

空位圖:前2個比特位被保留,值分別為0和1,以保證不會和OK、Error包的首字節沖突。在MySQL 5.0及之后的版本中,這2個比特位的值都為0。

字段值:行數據中的字段值,二進制形式。

4.3.9 PREPARE_OK 響應報文(Prepared Statement)

用於響應客戶端發起的預處理語句報文,組成結構如下:

結構 說明
[PREPARE_OK] PREPARE_OK結構
如果參數數量大於0  
[Field] 與Result Set消息結構相同
[EOF]  
如果列數大於0  
[Field] 與Result Set消息結構相同
[EOF]  

其中 PREPARD_OK 的結構如下:

字節 說明
1 OK報文,值為0x00
4 預處理語句ID值
2 列數量
2 參數數量
1 填充值(0x00)
2 告警計數

4.3.10 Parameter 響應報文(Prepared Statement)

預處理語句的值與參數正確對應后,服務器會返回 Parameter 報文。

字節 說明
2 類型
2 標志
1 數值精度
4 字段長度

類型:與 Field 結構中的字段類型相同。

標志:與 Field 結構中的字段標志相同。

數值精度:與 Field 結構中的數值精度相同。

字段長度:與 Field 結構中的字段長度相同。

5 參考資料

《MySQL Internals Manual: MySQL Client/Server Protocol》

原文: http://hutaow.com/blog/2013/11/06/mysql-protocol-analysis/


免責聲明!

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



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