崑崙資料庫 MySQL 連線協議簡介

KunlunDB發表於2022-07-12

崑崙資料庫的計算節點基於 PostgreSQL 研發,因而直接可以支援PostgreSQL 的連線協議,所以使用 JDBC、ODBC 等通用的資料庫連線協議以及使用各類程式語言的 PostgreSQL 專有的連線庫的軟體都可以連線到崑崙資料庫叢集並且正常工作。

為了讓原本使用 MySQL 的應用程式可以不需要修改也不需要重新編譯就能連線並且正常使用崑崙資料庫,我們開發了崑崙資料庫的 MySQL 連線協議,本文對此協議實現做一個簡介。

總的來說,對於 KunlunBase 來說,連線協議就是客戶端與 KunlunBase 伺服器通訊的管道,MySQL 和 PostgreSQL 協議就是兩種形狀不同的管道,而其中傳輸的 SQL 語句和查詢結果則本質上是相同的。

也就是說 KunlunBase 支援的任何 SQL 語法和功能都可以在 MySQL 和PostgreSQL 這兩種連線協議中的任何一種連線中傳輸到伺服器叢集中正常執行並收到其結果。

例如可以在 MySQL 連線中傳送 PostgreSQL 私有語法 SQL 或者標準 SQL 語句,包括 prepared statement 語法、儲存過程語法、DDL語法等,並且得到遵循MySQL協議的結果,從而可以使用 MySQL 客戶端庫完成結果讀取;也可以 在PostgreSQL 連線中傳送 KunlunBase 支援的任何 MySQL 私有語法(例如prepared statement、DML等)的 SQL語句或者標準 SQL 語句,並且得到遵循 PostgreSQL 的結果,從而可以使用 PostgreSQL 客戶端庫完成結果讀取。

崑崙資料庫MySQL協議支援的功能

崑崙資料庫MySQL協議支援所有常用功能,包括文字和二進位制協議,連線驗證(只支援mysql_native_password),資料壓縮,prepared statement,字符集,錯誤處理,SSL連線等。

一個Kunlun-server(計算節點)同時監聽2個TCP埠 — PostgreSQL協議的埠(預設5432)和MySQL協議的埠(預設5306),都可以透過配置檔案自定義配置。

MySQL 和 PostgreSQL 客戶端使用統一的使用者名稱和密碼連線 Kunlun-server,不論使用哪一種連線協議,Kunlun-server收到TCP連線請求後,會啟動本埠的服務端協議(即 PostgreSQL 或者 MySQL)處理模組,完成連線驗證,建立起有效的資料庫連線。

後續在這兩類連線中使用者可以傳送的 SQL 語句完全相同,與協議無關。

使用者可以在任何一類連線中傳送標準 SQL 語句,或者 PostgreSQL 或者MySQL 私有語法的 SQL 語句給崑崙資料庫並且獲得結果。

賬號和訪問控制

使用者透過 Kunlun-server 的 PostgreSQL 或者 MySQL 連線傳送 create user 語句建立使用者賬戶,這裡的 create user 語法(以及任何其他 DDL 語法)必須是 PostgreSQL 的語法。

DBA 透過在 pg_hba.conf 配置檔案中建立訪問控制規則,來可選地定義某些使用者賬號必須來自特定的IP或者域名,或者某個賬戶只能訪問某些 database等訪問控制規則。

關於在pg_hba.conf配置訪問控制規則,詳見PostgreSQL的文件。

錯誤處理

崑崙資料庫 MySQ L協議會自動把 PostgreSQL 的錯誤號被對映到對應的MySQL 錯誤號;MySQL 協議執行期間返回的錯誤則使用與 MySQL 的server 端協議實現完全相同的錯誤號。

因此應用程式原本處理 MySQL 錯誤的程式碼邏輯不需要任何修改就可以按照預期工作。

JDBC 等資料庫客戶端 API 庫基於異常類樹進行錯誤處理,每一個異常型別繫結若干個 MySQL 錯誤號,因此只要應用程式程式碼實現了異常捕捉,也可以正確地捕獲崑崙資料庫的MySQL連線返回的錯誤異常。

錯誤描述文字使用 PostgreSQL 的錯誤字串,而不是 MySQL 錯誤號對應的文字。

這通常不會成為問題,因為根據 MySQL 的文件,雖然錯誤號碼在所有MySQL版本中不變,但是錯誤描述並不承諾不變,所以應用程式本來也不應該基於錯誤字串的內容匹配來實現其功能邏輯。

另外,KunlunBase 支援 MySQL 的SHOW WARNINGS和SHOW ERRORS語句,並且其用法和效果與 MySQL 的相同語句完全相同。

字符集

MySQL客戶端可以按照其標準方式指定字符集,這個字符集如果崑崙資料庫不支援則連線失敗報錯。

PostgreSQL預設支援豐富的字符集,它與MySQL支援的字符集大部分是重合的,所有常見字符集兩者都支援,包括所有中文、日韓字符集以及主要歐洲(西中東歐)各語言字符集。

MySQL客戶端傳送到崑崙資料庫的任何字串,都會先轉換為當前資料庫的字符集再使用;返回給MySQL客戶端的任何字串都會先從當前資料庫的字符集轉回MySQL客戶端字符集再傳送。

不支援MySQL的set client/connection/server_character_set/collation
,但是支援SET NAMES 語法。

資料壓縮

支援使用zlib和zstd在傳輸資料包之前壓縮。

崑崙資料庫MySQL連線協議不支援的MySQL功能

只支援mysql_native_password 一種認證方法,不支援其他認證方法或者外部認證外掛。這對於自mysql-4.1以來的各個版本的MySQL客戶端都是沒問題的,它們都可以正確地連線上來並正常工作。

所有的密碼管理功能:

包括密碼過期,密碼驗證,雙密碼,密碼重用限制,多次密碼錯誤導致賬戶臨時鎖定等。所有此類功能都使用PostgreSQL原有的功能。

賬戶管理的不常用功能:

代理使用者(proxy user),未知、匿名使用者、賬戶鎖定,賬戶資源限制。

使用text協議傳送prepared statement:

生產系統中應該使用binary連線執行prepared statement,這才是其設計初衷,也是崑崙資料庫的MySQL協議支援的。

text協議執行prepare/execute命令無論對於MySQL還是PostgreSQL都僅僅是用於開發和除錯,而崑崙資料庫並不支援mysql的prepare/execute語法,並且沒有MySQL的使用者自定義變數這個功能,也就無法按照mysql prepare statement的方式繫結引數。

init_connect 語句初始化連線狀態:

該功能知道的使用者很少,而且在連線 初始化好之前執行SQL語句本來也不符合資料庫系統的設計原理,因此在崑崙資料庫中不支援。

session state tracking:

因為MySQL維護的那些status變數,在崑崙資料庫的計算節點中並不存在。因此也不支援mysql_session_track_xxx系列客戶端API函式。

但是同時,崑崙資料庫繼承了PostgreSQL的pgstat 基礎設施,pgstat可以收集非常豐富的系統執行時統計資訊,MySQL和PostgreSQL客戶端都可以透過查詢pgstat的一系列檢視和函式,可以得到這些資訊。

詳見 PostgreSQL 的 pgstat 文件。

崑崙資料庫MySQL服務端協議與MySQL服務端協議不同的功能

連線的目標資料庫

當MySQL客戶端連線崑崙資料庫計算節點時沒有指定資料庫名稱,那麼預設連線到 “postgres” 資料庫,這一點與MySQL的行為是不同的 — MySQL在這種情況下不指定當前資料庫。

同時,MySQL支援使用use db語句或者使用 mysql_select_db()客戶端API來切換當前資料庫,但是postgres並不允許在一個活躍連線中切換資料庫,詳見下文。

資料輸出格式

對於所有資料型別,崑崙資料庫都使用 PostgreSQL 的輸出函式來生成文字協議下的查詢結果,這意味著decimal/numeric, float,real(double), date, timestamp, timestamptz, time型別的輸出結果在個別情況下可能會與 MySQL 的輸出的欄位值文字表示有細微差別 — 由於數值型別是因為序列化的浮點數精度差異;日期時間型別是因為locale設定或者時區資訊,例如 PostgreSQL 的timestamptz型別欄位值總是帶有時區值,例如”2022-5-30 21:08:35+08”。

如果使用 binary 協議(也就是使用prepared statement,bind引數和結果),則沒有這些差別。

崑崙資料庫支援的MySQL命令

在崑崙資料庫的MySQL連線中,MySQL客戶端軟體除了可以傳送SQL語句(即COM_QUERY命令)之外,還可以傳送若干種其他命令,具體包括:

改變連線狀態的命令及其對應的MySQL客戶端API:

COM_SET_OPTION:mysql_set_server_option()
COM_RESET_CONNECTION:
mysql_reset_connection()
COM_PING:mysql_ping()
COM_QUIT:
mysql_close()

Prepared statement 相關的命令:

COM_STMT_EXECUTE
COM_STMT_FETCH
COM_STMT_PREPARE
COM_STMT_SEND_LONG_DATA
COM_STMT_RESET
COM_STMT_CLOSE

崑崙資料庫不支援的MySQL命令

崑崙資料庫不支援的 MySQL 命令包括所有deprecated(過時的,即將在未來版本去除)的命令,replication和 clone 相關的命令,以及mysql server內部使用的(客戶端不可以使用的)命令。

如果應用程式呼叫 MySQL 客戶端 API 執行下列不支援的命令,則崑崙資料庫計算節點會返回標準的 MySQL 錯誤1047(不支援的命令)。

崑崙資料庫不支援的 MySQL 命令如下:

  • COM_PROCESS_KILL:mysql_kill() 已過時,使用kill connection/query,不過崑崙資料庫目前不支援此命令
  • COM_PROCESS_INFO:
  • mysql_list_processes() 已過時,使用show
  • processlist,崑崙資料庫目前已支援此命令
  • COM_BINLOG_DUMP_GTID:replication命令,備節點IO執行緒連線主節點時使用
  • COM_BINLOG_DUMP:replication命令,備節點IO執行緒連線主節點時使用
  • COM_REFRESH:更新使用者賬戶和訪問控制資訊。崑崙資料庫不需要使用者顯示地重新整理快取,而是完全自動的探測到任何後設資料表發生變化並且自動更新快取的對應資訊。不支援此命令或者對應的mysql_reload(), mysql_refresh()函式
  • COM_STATISTICS:崑崙資料庫中統計資訊使用pgstat的設施獲得,不支援mysql_stat() API 函式或者mysqladmin獲取統計資訊
  • COM_DEBUG:mysql_debug() 函式,僅在開發人員除錯時使用,生產系統中無法使用。
  • COM_REGISTER_SLAVE:replication命令,備節點IO執行緒連線主節點時使用
  • COM_CLONE:clone命令
  • COM_FIELD_LIST:mysql_list_fields()已過時,使用show columns,不過崑崙資料庫目前不支援此命令,使用者需要查詢pg_attribute等後設資料表獲得列的後設資料
  • COM_SLEEP:不是客戶端傳送的,內部使用
  • COM_CONNECT:連線建立後就不可以傳送此命令
  • COM_TIME:不是客戶端傳送的,內部使用
  • COM_DELAYED_INSERT:在mysql中已去除
  • COM_END:不是客戶端傳送的,內部使用
  • 不支援mysql_set_local_infile_xxx()系列函式

切換會話當前資料庫和使用者命令:

COM_INIT_DB:在MySQL連線中切換當前資料庫,也即是use db語句的命令版本。在崑崙資料庫中這兩種方式切換database都不支援。

PostgreSQL 要求客戶端連線到一個database後始終使用它,不可以切換。

同時 PostgreSQL 提供了schema這個概念,它是一個邏輯層面的名字空間。

在 PostgreSQL 中一個database裡面可以建立任意數量的schema, database和schema之外的資料庫物件(比如表,索引,檢視,儲存過程,sequence等)都一定屬於某個schema(名字空間)。

引用這些資料庫物件時候,如果不指定schema名稱,那麼就是在一個稱為search_path變數的名字空間列表中依次按名字尋找這個物件。在一個連線中可以動態的修改search_path變數來修改名字空間查詢的schema序列,使用PostgreSQL的語法set search_path。

崑崙資料庫完全繼承了這些特徵。在一個MySQL連線中如果要切換schema,那麼執行PostgreSQL的set search_path即可。
MySQL 的database概念其實是資料庫物件的物理(目錄儲存位置)和邏輯(名字空間)合併為一體了,而 PostgreSQL 則把它們分開,實現了更大的靈活性和自由度。

COM_CHANGE_USER:在MySQL中這個命令除了可以切換當前使用者之外,還可以切換database。由於上述原因,我們不支援切換資料庫,但是可以切換當前使用者,所以只有mysql_change_user()函式呼叫指定的database name與當前連線已經連線的資料庫相同時候,才可以正確執行,否則呼叫失敗返回錯誤。另外,使用者也可以執行PostgreSQL的set session authorization,set role等命令做使用者/角色切換。

MySQL語法相容性

  1. postgreSQL要求識別符號名稱位元組數<64, 意味著如果識別符號是中文的話,中文識別符號最大字元數M在一個範圍內變化,最小的M不到20個字元。這裡的識別符號包括database,table,column,procedure等。

  2. 崑崙資料庫支援常用的 MySQL 私有的DML語法以及變數讀寫語法 。並且無論在使用 PostgreSQL 協議的連線還是 MySQL 協議的連線中,都可以執行崑崙資料庫支援的任何語法,包括這些 MySQL 私有 DML 語法,也包括標準的SQL語法,以及崑崙資料庫支援的任何其他 PostgreSQL 私有語法。

  3. KunlunBase支援autoincrement關鍵字定義列為自增列,也支援last_insert_id()函式,其用法與mysql完全相同

  4. KunlunBase支援MySQL的所有私有資料型別,包括:

  • TINYBLOB, BLOB, MEDIUMBLOB, LONGBLOB, VARBINARY, BINARY
  • 在KunlunBase中統一按照bytea型別來儲存和處理
  • TINYTEXT, MEDIUMTEXT, LONGTEXT
  • 在KunlunBase中都統一按照text型別來儲存和處理
  • DOUBLE (不帶 PRECISION)
  • byte, tinyint, mediumint, middleint, 以及所有整形型別的UNSIGNED 修飾符
  • DATETIME:不帶時區資訊的時間戳。
  • TIMESTAMP

在 MySQL 和PostgreSQL中TIMESTAMP型別有不同的意義:在MySQL中它表示帶有時區資訊的時間戳,在PostgreSQL中表示不帶時區資訊的時間戳。為了與二者都保持一致,在KunlunBase中,在 MySQL 連線中遵循MySQL的定義,在 PostgreSQL 連線中遵循PostgreSQL的定義。

  1. 崑崙資料庫不支援 MySQL 儲存過程或者 MySQL 專有的 DDL 語法以及諸如 show 系列的命令,load data infile 命令等等任何 MySQL 特有功能的語法。

SSL支援

目前我們還沒有實現崑崙資料庫 MySQL 協議的 SSL 支援,在未來的版本中會支援 SSL 連線。目前應用程式無法呼叫任何 MySQL 客戶端 SSL API 與崑崙資料庫工作。

END


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70011764/viewspace-2905350/,如需轉載,請註明出處,否則將追究法律責任。

相關文章