從通信協議看MySQL客戶端與中間件設計
本文以UPSQL Proxy 2.4.0中關鍵的報文流式處理為例,介紹MySQL通信協議,以及與客戶端的關系。
MySQL通信協議協議介紹
在執行MySQL查詢,如“selecet * from test”時,MySQL的應答包被稱為ResultSet,其為一組邏輯包(協議包),如圖1所示包含兩個部分:
- 1. 元數據,包含如下數據包:
- - Field_Count:列的個數
- - Field:列的描述,一般為多個
- - Eof:在列信息描述,或數據發送完畢時候,用以標記一段數據的發送結束。在較高版中,該數據包被取消。
- 2. 行數據,包含:
- - Row:一行數據的內容,多行時會出現多個
- - Err:描述錯誤,出現錯誤時,為最后一個邏輯包
- 或
- - OK:在較高版本協議中,用以替換Eof包,用以傳輸更多信息
圖1 MySQL結果集報文結構
客戶端庫接口介紹
由此MySQL CAPI中提供了兩套函數接口:
- - mysql_store_result/mysql_stmt_store_result
- - mysql_use_result
- 一般而言,這兩套接口的區別是:
- - mysql_store_result/mysql_stmt_store_result: 將結果存儲在應用內存
- - mysql_use_result: 數據保存在tcp buffer或數據庫server端
但從通信過程的角度來看:
- - mysql_store_result/mysql_stmt_store_result: 需要等待所有數據傳輸完畢,并且客戶端解析完畢
- - mysql_use_result: 簡單而言只要得到row數據包,就可以向上層api返回數據
- 所以,我們內部將mysql_use_result稱為流式處理,流式處理有2大優點:
- - 應用層響應速度更快,因為不需要等待收齊結果集
- - 內存管理更可控,可以避免客戶端內存不足
在mysql客戶端以及mysqldump命令中,有如下參數:
- - --quik/-q,即使用mysql_use_result,進行流式處理,可以避免mysqldump大數據量下oom
JDBC在設計上封裝性更高,一般而言其邏輯與CAPI的
- mysql_store_result/mysql_stmt_store_result處理邏輯一樣,但有2個方法可以將其轉換為流式處理模式:
- - 代碼層面:prepareStatement第2、3個參數設置為ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY
- - JDBC URL設置(不修改代碼):增加參數useCursorFetch=true&defaultFetchSize=-2147483648 (該方法在不同版本的jdbc驅動上表現有區別,不建議采用)
API與協議解析的關系圖2所示:
▲ 圖2 API與協議解析
UPSQL Proxy中間件設計
在UPSQL Proxy 2.4.0以前使用的是阻塞模式,即往多個后端收齊結果集后,再向用戶應答,這樣有2個缺點:-
- 響應時延延長
- Proxy層內存控制,導致生產環境不支持大于分庫下10w行以上數據量返回
UPSQL Proxy 2.4.0實現了流式處理,簡單而言就是,將行信息盡快以流的形式發給客戶端而不是等中間件收齊后發送,邏輯如圖3所示:
▲ 圖3 UPSQL Proxy的流式處理
即在分庫場景下,會并發訪問各個數據節點,當得到一個完整的元數據后,就可以立刻返回給請求方,之后接收到行數據后,都可以及時的返回給請求方,以此降低中間件的內存需求,同時提高客戶端的相應速度。
總結
本文介紹了銀聯自研中間件UPSQL Proxy早前的一次關鍵功能迭代,希望能讓大家感受到MySQL協議的魅力。
福利時間(目前投遞會有作者的內推機會哦 🙌🏻🙌🏻🙌🏻):
中國銀聯云計算中心社會招聘崗位正在火熱招錄中,目前開放投遞的崗位如下:
1、運營服務
2、系統運維
3、操作系統開發
4、數據庫開發(云計算方向)
5、開源組件
6、綜合文秘
有意向者可打開鏈接【可復制到瀏覽器或者點擊閱讀原文】 https://join.unionpay.com 選擇“社會招聘”分類進行投遞。【注:內推請填寫 周家晶及工號:01362912為推薦人】