分散式 | DBLE 的 general 日誌實現

愛可生雲資料庫發表於2021-09-30

作者:文韻涵

愛可生 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 :

  1. SELECT SCHEMA_NAME FROM INFORMATION_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; – 查詢所有庫
  2. 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 中配置,在這個配置中的更變,需要充氣後才能生效。

相關命令
  1. show @@general_log; – 查詢 general log 的開關狀態和檔案路徑
  2. enable @@general_log; – 開啟 general log
  3. disable @@general_log; – 關閉 general log
  4. 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 時

相關文章