目錄
- 目錄
- 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 消息體
- 3.1 消息頭
- 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)
- 4.1 登陸認證交互報文
- 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 客戶端命令請求報文(客戶端 -> 服務器)
命令:用於標識當前請求消息的類型,例如切換數據庫(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 |
數值精度:該字段對DECIMAL
和NUMERIC
類型的數值字段有效,用於標識數值的精度(小數點位置)。
默認值:該字段用在數據表定義中,普通的查詢結果中不會出現。
附: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/