作者:文韻涵
愛可生 DBLE 團隊開發成員,主要負責 DBLE 需求開發,故障排查和社群問題解答。
本文來源:原創投稿
*愛可生開源社群出品,原創內容未經授權不得隨意使用,轉載請聯絡小編並註明來源。
問題背景
在使用某些 GUI 工具連線 DBLE 操作時,會因為某些 SQL 在 DBLE 中不相容導致 GUI 工具出現異常不能正常使用。
通常排查方案:
- 步驟一:需要知道 GUI 工具操作時下發了哪些 SQL 至 DBLE ;一般用 tcpdump 、Wireshark 等抓包工具獲取 SQLs
- 步驟二:將 SQLs 逐個在 Mysql Client 中執行,定位問題 SQL
排查案例1
登陸 phpMyAdmin 首個介面,未展示資料庫列表
GUI 工具: phpMyAdmin 7.4.20 (這裡用的是docker)
DBLE 版本:3.21.02.x
##docker方式搭建phpMyAdmin
## 拉取phpmyadmin映象
$ docker pull phpmyadmin/phpmyadmin
##初始化phpmyadmin容器 且關聯dble服務
$ docker run -d --name myadmin_aliyun -e PMA_HOST=xxx.mysql.rds.aliyuncs.com -e PMA_PORT=3xx6 -p 8081:80 phpmyadmin/phpmyadmin
##詳解:
-d:以後臺模式執行
--name myadmin: 容器命名為 myadmin, 容器管理時用(啟動/停止/重啟/檢視日誌等)
-e PMA_HOST=xx.xxx.xx.xx: Dble伺服器域名或IP地址
-e PMA_PORT=8066: Dble的8066埠
-p 8080:80: 埠對映, 本地埠:容器埠, 訪問: http://ip:8080
phpmyadmin/phpmyadmin: 要初始化的映象名
訪問 http://ip:8080 ,使用 DBLE 的 8066 使用者密碼登陸;登入後的介面發現未展示資料庫列表,如下圖:
為什麼沒有展示資料庫列表呢?
排查步驟一:
先下載 tcpdump(用於抓包)、Wireshark(檢視包)工具;然後執行 tcpdump 命令採集操作(登入 phpmyadmin 後的介面)期間的 tcp 協議傳輸生成 cap 檔案,然後將其檔案放置 Wireshark 中轉成 Mysql 協議然後過濾(如下圖)方便閱讀、排查以及提取下發的所有 SQLs ;(實際上需要逐個點開 Request Query 然後手動提取 SQL )
排查步驟二:
將收集的 SQLs 逐個在 Mysql Client 中執行,定位到問題 SQL (原因:phpMyAdmin 下發查詢庫列表時,DBLE 返回空結果集)
具體問題 SQL :
- SELECT
SCHEMA_NAME
FROMINFORMATION_SCHEMA
.SCHEMATA
, (SELECT DB_first_level FROM ( SELECT DISTINCT SUBSTRING_INDEX(SCHEMA_NAME, '_', 1) DB_first_level FROM INFORMATION_SCHEMA.SCHEMATA WHERE TRUE ) t ORDER BY DB_first_level ASC LIMIT 0, 100) t2 WHERE TRUE AND 1 = LOCATE(CONCAT(DB_first_level, '_'), CONCAT(SCHEMA_NAME, '_')) ORDER BY SCHEMA_NAME ASC; – 查詢所有庫 - 2021-08-06T15:33:28.350 9 Query SELECT COUNT(*) FROM ( SELECT DISTINCT SUBSTRING_INDEX(SCHEMA_NAME, '_', 1) DB_first_level FROM INFORMATION_SCHEMA.SCHEMATA WHERE TRUE ) t; – 查詢庫的個數
在步驟一中,需要用到額外工具協助排查,可能需要儲備一些知識(如:TCP 協議、抓包命令);於是,非開發人員排查此問題是比較苦惱的。
general log
開啟 general log ,將所有到達 DBLE 的 SQL 語句記錄下來。這樣一來不再需要使用抓包工具就可以拿到所有 SQLs(直接進入步驟二)
具體見general日誌:
https://actiontech.github.io/...
相關引數
- enableGeneralLog:general log 的開關標識,1-開啟、0-關閉
- generalLogFile:general log 檔案的儲存路徑
- generalLogFileSize:觸發檔案翻轉的大小,當超過16MB則將 general.log 翻轉為 yyy-MM/general-MM-dd-%d.log 的格式檔案
- generalLogQueueSize:內部實現機制佇列用到的大小,預設4096
以上引數在 bootstrap.cnf 中配置,在這個配置中的更變,需要充氣後才能生效。
相關命令
- show @@general_log; – 查詢 general log 的開關狀態和檔案路徑
- enable @@general_log; – 開啟 general log
- disable @@general_log; – 關閉 general log
- reload @@general_log_file='/tmp/dble-general/general/general.log'; -- 修改 general log 的檔案路徑
以上命令僅管理端支援執行,立即生效,不需要重啟 DBLE 。另外下次重啟 DBLE 的時候會保留當前設定,不會丟失。
版本
- 從 DBLE3.21.02 版本開始引入 general log ;(之前的版本不支援)
效能
- 開啟 general log 後,DBLE 效能損耗在3~5%之間;建議在排查某些錯誤臨時開啟,等除錯完後關閉
輸出型別
- 與 Mysql 相比,DBLE 的 general log 的輸出型別只有 File 模式
列印格式
- 開啟後,記錄格式(與 Mysql 的 general log 格式一致)
/FAKE_PATH/mysqld, Version: FAKE_VERSION. started with:
Tcp port: 3320 Unix socket: FAKE_SOCK
Time Id Command Argument
2021-08-05T16:24:53.558 1 Query select * from no_sharding_t1
2021-08-05T16:25:00.210 1 Query desc tb_grandson1
2021-08-05T16:26:32.774 1 Query desc sharding_2_t1
2021-08-05T16:26:37.990 1 Query select * from sharding_2_t1
2021-08-05T16:26:54.862 1 Query insert into sharding_2_t1 values(1,1,1,1,1)
實現機制
DBLE 中 general log 的非同步落盤機制具體的實現參考log4j
具體實現
同步處理
- 將 sql 包裝為 Log ;Log 包含 Time、Id、Command、Argument 等資訊
- 將 Log 放置 generalLog 佇列中;(若佇列已滿時,會一直阻塞在此處,直到佇列有空閒位置)
- sql 的後續流程處理
非同步處理
- 監聽佇列且處理佇列
- 當前 Log 的 byte 大小 <= Buffer 快取剩餘空間(預設4096),則先入 Buffer 快取中;後續 Buffer 快取滿了會觸發落盤
- 當前 Log 的 byte 大小 > Buffer 快取剩餘空間, 先將 Buffer 快取中的 Log +當前 Log 直接落盤
- 因為採用了 Disruptor(generalLog 實際上是一個環形佇列),入隊計算會決定是否為批量處理的狀態,如果為批量處理,也會觸發將 Buffer 快取中的 Log/ 當前 Log 的落盤
- 翻轉條件:日期變動(每天) || general.log 的大小>generalLogFileSize 時