上次在這裡問多語系 README 的問題,得到不少實用的回覆,謝謝各位。這次想問一個更技術的,我們內部卡了一陣子。
先說身分,免得被當成來打廣告的:我是一個 MIT 授權開源資料庫工具的維護者之一。下面的數字都是連真實實例跑出來的,不是抄文件。
我們寫了 16 個驅動,實際連上 42 種資料庫。其中 26 種沒有自己的驅動,是借別人的通訊協議進來的——最常見的就是「相容 MySQL 協議」。
問題是:協議相容,不等於行為相容。 而且不相容的地方常常「看起來正常」,這才是最麻煩的。
舉幾個我們實際踩到的:
version() 回傳 5.1.0,一個不存在的 MySQL 版本。真實建號只在 current_version() 裡。Apache Doris 回 5.7.99,而且它連 current_version() 都沒有,真實版本只在 @@version_comment。SHOW STATUS LIKE '...' 直接解析錯誤(mismatched input 'LIKE'),但不帶 LIKE 的裸 SHOW STATUS 是接受的,只是回零行。information_schema.PROCESSLIST 這張表。information_schema.statistics 永遠是空的,索引一個都報不出來,即使索引確實建了。SHOW CONSTRAINTS 也列得出來,但 KEY_COLUMN_USAGE 是 0 行,而且約束根本不生效——我們插了一筆引用不存在客戶的訂單,插進去了。BASE TABLE 的 INDEX_LENGTH 回 NULL,於是 DATA_LENGTH + INDEX_LENGTH 整個被 NULL 汙染。KILL QUERY,跑著的查詢殺不掉。同一類的:EXPLAIN 在 MySQL 系裡至少三種寫法(EXPLAIN、EXPLAIN FORMAT=JSON、EXPLAIN JSON),Doris 和 StarRocks 的 JSON 版都解析不過。
不是全部都是人家的問題,至少兩處是我們的:
mysql2 的 execute()(二進位 prepared 協議),包括沒參數的。SHOW、EXPLAIN 這類在不少相容引擎的 prepared 協議裡沒實作,於是 SingleStore 掛了四個功能、StarRocks 掛了兩個。改成沒參數的走文字協議就全好了。COALESCE。不是它先報零,是我們自己把能讀到的也弄沒了。
我們現在的做法是:在連線建立的當下做一輪能力偵測,把「這台伺服器接受哪種 EXPLAIN 寫法」「有沒有 PROCESSLIST」這類問題先問清楚,再按結果決定後面怎麼發。不寫死一種語法然後在出錯分支裡猜。
但這樣連線會變慢,而且偵測本身也要維護。
想聽聽各位的做法:
上面每條都標了測試時的版本,換個版本結論可能就不一樣了。如果哪一條和各位的實測對不上,很想知道。