新特性解讀 | MySQL 8.0錯誤日誌深入過濾(上)

愛可生雲資料庫發表於2022-04-13

作者:楊濤濤

資深資料庫專家,專研 MySQL 十餘年。擅長 MySQL、PostgreSQL、MongoDB 等開源資料庫相關的備份恢復、SQL 調優、監控運維、高可用架構設計等。目前任職於愛可生,為各大運營商及銀行金融企業提供 MySQL 相關技術支援、MySQL 相關課程培訓等工作。

本文來源:原創投稿

*愛可生開源社群出品,原創內容未經授權不得隨意使用,轉載請聯絡小編並註明來源。

--

MySQL 8.0 有一個元件叫 component_log_filter_dragnet , 它主要功能就是對 MySQL 的錯誤日誌內容進行定製化過濾與改造,之前有簡單提過,這次來詳細說下如何使用。

使用前,先安裝元件:

INSTALL COMPONENT 'file://component_log_filter_dragnet'; 

安裝後,設定系統引數log_error_services 來啟用它。

SET global log_error_services = 'log_filter_dragnet; log_sink_internal';

通過系統引數dragnet.log_error_filter_rules 來調整過濾規則,比如對指定錯誤程式碼限流、改造輸出等等。類似對MySQL監控,必須有過濾條件、觸發動作、最終結果等關鍵因素。 過濾條件則類似SQL語句中單個欄位或者多個欄位組合過濾。比如欄位<操作符> 值、NOT EXISTS 欄位、過濾條件組合等。存在三種欄位:分別為核心欄位,可選欄位,使用者自定義欄位。

本篇我們來介紹核心欄位。
核心欄位列表如下:
  1. time: 時間,比如可以設定在2022年12月1日之前都不允許寫錯誤日誌。
  2. msg: 錯誤資訊, 由於err_code直接能定位到msg,一般很少用它來判斷,msg可以參與定製內容。
  3. prio:優先順序,對應的值為ERROR、WARNING、INFORMATION、NOTE幾個值或者任意組合,與設定系統引數log_error_verbosity 效果類似。
  4. err_code/SQL_state: 具體錯誤程式碼,也即錯誤資訊的KEY。
  5. err_symbol: 具體錯誤符號,MySQL每個錯誤程式碼都對應一個錯誤符號。具體的err_symbol 資料可以用perror 列印或者從官網錯誤參考頁面查詢:https://dev.mysql.com/doc/mys...
  6. subsystem: 指定過濾的子系統專案,比如:Server、InnoDB等。
觸發動作有以下四個:
  1. drop: 刪除錯誤資料。
  2. throttle: 對內容限流。
  3. set:定製欄位資料。
  4. unset: 重置欄位資料。

本篇要改造的錯誤日誌基於如下命令產生:全篇用命令A代替。

[root@ytt-pc ytt]# mysql -utest33333 
ERROR 1045 (28000): Access denied for user 'test33333'@'localhost' (using password: NO)

對應的錯誤日誌程式碼:從結果擷取兩個err_code 分別為MY-013360和MY-010926。

2022-03-24T06:03:59.511173Z 50 [Warning] [MY-013360] [Server] Plugin sha256_password reported: ''sha256_password' is deprecated and will be removed in a future release. Please use caching_sha2_password instead'
2022-03-24T06:03:59.511322Z 50 [Note] [MY-010926] [Server] Access denied for user 'test33333'@'localhost' (using password: NO)
接下來我舉例說明一些常見用法:
  1. 欄位time

類似對錶時間欄位進行過濾,可以定義一個等值條件或者取值範圍。例如讓2023-01-01之前的錯誤資料不記入日誌,配合欄位time以及動作drop來實現:

   ytt-pc:ytt:8.0.28>set global dragnet.log_error_filter_rules='if time <''2023-01-01'' then drop .';
   Query OK, 0 rows affected (0.00 sec)

退出執行命令A,只要時間還沒到2023年,錯誤日誌裡就不會記錄任何資料。

  1. 欄位prio.

比如可以用欄位prio來遮蔽warning資料,讓其不計入錯誤日誌,實現如下:

   ytt-pc:(none):8.0.28>set global dragnet.log_error_filter_rules='if prio==warning then drop .';
   Query OK, 0 rows affected (0.00 sec)

退出執行命令A,完了檢視錯誤日誌:日誌裡只保留Note資料,warning資料沒有記入。

   2022-03-24T06:05:41.037512Z 52 [Note] [MY-010926] [Server] Access denied for user 'test33333'@'localhost' (using password: NO)
  1. 欄位err_code/SQL_state.

err_code 最直接,只要查到錯誤程式碼,根據err_code來過濾即可。比如禁止錯誤程式碼為MY-010926的資料記入日誌,可以直接用err_code=MY-010926來過濾,實現如下:

   ytt-pc:ytt:8.0.28>set global dragnet.log_error_filter_rules='if err_code==MY-010926 then drop .';
   Query OK, 0 rows affected (0.00 sec)

退出執行命令A,完了檢視錯誤日誌:不存在錯誤程式碼為MY-010926的資料。

   2022-03-24T06:08:47.771611Z 53 [Warning] [MY-013360] [Server] Plugin sha256_password reported: ''sha256_password' is deprecated and will be removed in a future release. Please use caching_sha2_password instead'

假設想定製錯誤程式碼,把它們改造成MySQL官網錯誤參考頁面查不到的值,可以配合動作set來實現:

   ytt-pc:ytt:8.0.28>set global dragnet.log_error_filter_rules='if err_code==MY-010926 or err_code==MY-013360  then set err_code=1234567890 .';
   Query OK, 0 rows affected (0.00 sec)

退出執行命令A,完了檢視錯誤日誌:相關錯誤程式碼全部替換為MY-1234567890

   2022-03-24T06:12:37.456522Z 55 [Warning] [MY-1234567890] [Server] Plugin sha256_password reported: ''sha256_password' is deprecated and will be removed in a future release. Please use caching_sha2_password instead'
   2022-03-24T06:12:37.456676Z 55 [Note] [MY-1234567890] [Server] Access denied for user 'test33333'@'localhost' (using password: NO)

假設想定製錯誤資料,可以在set動作時,更新欄位msg的值,實現如下:

   ytt-pc:ytt:8.0.28>set global dragnet.log_error_filter_rules='if err_code==MY-010926 or err_code==MY-013360  then set msg=''你來看哦,沒有了哦!!!'' .';
   Query OK, 0 rows affected (0.00 sec)

退出執行命令A,完了檢視錯誤日誌:錯誤資料已經被重新定製。

   2022-03-24T06:16:05.617758Z 56 [Warning] [MY-013360] [Server] 你來看哦,沒有了哦!!!
   2022-03-24T06:16:05.617898Z 56 [Note] [MY-010926] [Server] 你來看哦,沒有了哦!!!

以上err_code也可以直接替換為對應的SQL_state,效果一樣。比如:sql_state='HY000'(這裡是字串)。

  1. 欄位err_symbol

之前說過,err_symbol和err_code類似,通過perror列印這兩個錯誤程式碼對應的err_symbol如下:括號裡大寫的兩串字元。

   [root@ytt-pc ytt]# perror MY-013360 MY-010926
   MySQL error code MY-013360 (ER_SERVER_WARN_DEPRECATED): '%s' is deprecated and will be removed in a future release. Please use %s instead
   MySQL error code MY-010926 (ER_ACCESS_DENIED_ERROR_WITH_PASSWORD): Access denied for user '%-.48s'@'%-.64s' (using password: %s)

現在來由err_symbol實現剛才err_code定製的msg資料:

   ytt-pc:ytt:8.0.28>set global dragnet.log_error_filter_rules='if err_symbol==''ER_SERVER_WARN_DEPRECATED''  or err_symbol==''ER_ACCESS_DENIED_ERROR_WITH_PASSWORD'' then set msg=''你來看哦,沒有了哦!!''.';
   Query OK, 0 rows affected (0.00 sec)
  1. 欄位subsystem

假設要遮蔽Server級別的錯誤(本篇這兩個錯誤程式碼對應的資料也是Server級別的),實現如下:

   ytt-pc:(none):8.0.28>set global dragnet.log_error_filter_rules='if subsystem==''Server'' then drop .';
   Query OK, 0 rows affected (0.00 sec)

退出執行命令A,再次檢視錯誤日誌:Server級別的錯誤資料都沒記入日誌。

  1. 動作復原命令:unset

unset 可以初始化具體的欄位,比如初始化這兩個錯誤程式碼對應的msg,實現如下:

   ytt-pc:ytt:8.0.28>set global dragnet.log_error_filter_rules='if err_code==MY-010926 or err_code==MY-013360  then unset msg .';
   Query OK, 0 rows affected (0.00 sec)

退出執行命令A,完了檢視錯誤日誌:資料變為“No error message, or error message of non-string type. This is almost certainly a bug!”

   2022-03-24T06:24:14.846763Z 59 [ERROR] [MY-013360] [Server] No error message, or error message of non-string type. This is almost certainly a bug!
   2022-03-24T06:24:14.846925Z 59 [ERROR] [MY-010926] [Server] No error message, or error message of non-string type. This is almost certainly a bug!
  1. 動作限流命令:throttle

假設這兩個錯誤資料在日誌裡只能記錄兩條,實現如下:

   ytt-pc:ytt:8.0.28>set global dragnet.log_error_filter_rules='if err_code==MY-010926 or err_code==MY-013360 then throttle 2 .';
   Query OK, 0 rows affected (0.00 sec)

無論執行多少次命令A,同樣的錯誤資料在日誌裡只記錄兩條。

假設限制這兩個錯誤資料在日誌裡每分鐘記錄2條,實現如下:

ytt-pc:ytt:8.0.28>set global dragnet.log_error_filter_rules='if err_code==MY-010926 or err_code==MY-013360 then throttle 2/60 .';
   Query OK, 0 rows affected (0.00 sec)

效果為錯誤日誌以分鐘級別記錄這兩條資料。

  1. 在條件里加上稍微複雜的判斷條件

假設錯誤程式碼MY-010926 對應的msg被定製為“好的,就這樣!”,錯誤程式碼MY-013360對應的msg被定製為“不錯哦,就這樣吧!”,實現如下:

   ytt-pc:ytt:8.0.28>set global dragnet.log_error_filter_rules='if err_code==MY-010926 then set msg=''好的,就這樣!'' elseif err_code==MY-013360 then set msg=''不錯哦,就這樣吧!'' .';
   Query OK, 0 rows affected (0.00 sec)

退出執行命令A,完了檢視錯誤日誌:msg 被對應的定製資料分別覆蓋。

   2022-03-24T06:32:06.505039Z 60 [Warning] [MY-013360] [Server] 不錯哦,就這樣吧!
   2022-03-24T06:32:06.505296Z 60 [Note] [MY-010926] [Server] 好的,就這樣!

由於內容較多,我分成了兩部分,第一部分就到此為止。

相關文章