MySQL ヒストリーに記録されない条件
TL; DR;
*IDENTIFIED*:*PASSWORD*
にマッチしたクエリ、つまりパスワードを含むクエリはヒストリーに記録されない- 環境変数
MYSQL_HISTIGNORE
で記録しないクエリを追加指定できる
ヒストリーに記録されない時がある
mysql
コマンド には履歴機能があります。
Linuxのシェルのように、過去に実行したSQLを上の矢印キーで遡ったり、Ctrl-R でキーワード検索することが出来ます。
時々、ヒストリーに記録されないSQLがあることが気になっていました。 今回はその条件を調べてみました。
ソースから辿ってみる
client/mysql.cc
を読んでいきます。
add_filtered_history()
という関数でヒストリーファイルに追記しています。
ignore_matcher
がヒストリーに残さないものを判定していそうです。
2929 /* Add the given line to mysql history and syslog. */ 2930 static void add_filtered_history(const char *string) { 2931 // line shouldn't be on history ignore list 2932 if (ignore_matcher.is_matching(string, charset_info)) return; 2933 2934 #ifdef HAVE_READLINE 2935 if (!quick && not_in_history(string)) add_history(string); 2936 #endif 2937 2938 if (opt_syslog) add_syslog(string); 2939 }
ignore_matcher
は 以下の箇所で定義されており、HI_DEFAULTS
がデフォルト値です。
そして、 MYSQL_HISTIGNORE
という環境変数でヒストリーに記録しないパターンを追加できることもわかりました。
1349 if (!status.batch) { 1350 // history ignore patterns are initialized to default values 1351 ignore_matcher.add_patterns(HI_DEFAULTS); 1352 1353 /* 1354 Additional patterns may be supplied using either --histignore option or 1355 MYSQL_HISTIGNORE environment variable. If supplied, they'll get appended 1356 to the default patterns. In case both are specified, pattern(s) supplied 1357 using --histignore option will be used. 1358 */ 1359 if (opt_histignore) 1360 ignore_matcher.add_patterns(opt_histignore); 1361 else if (getenv("MYSQL_HISTIGNORE")) 1362 ignore_matcher.add_patterns(getenv("MYSQL_HISTIGNORE"));
HI_DEFAULTS
は以下のように定義されていました。
パスワードが入っているSQLをヒストリーに記録してしまうと、ヒストリーファイルからパスワードが読み取られてしまうリスクがあるため、記録しないということでしょう。
132 /** default set of patterns used for history exclusion filter */ 133 const static std::string HI_DEFAULTS("*IDENTIFIED*:*PASSWORD*");
MYSQL_HISTIGNORE を試してみる
環境変数 MYSQL_HISTIGNORE
で無視する条件を追加してみます。
HIMITSU
を含んだSQLをヒストリーに記録しないようにします。
$ export MYSQL_HISTIGNORE='*HIMITSU*' $ mysql mysql> SELECT 'HOGEHOGE'; +----------+ | HOGEHOGE | +----------+ | HOGEHOGE | +----------+ 1 row in set (0.00 sec) mysql> SELECT 'HIMITSU NO HOGEHOGE'; +---------------------+ | HIMITSU NO HOGEHOGE | +---------------------+ | HIMITSU NO HOGEHOGE | +---------------------+ 1 row in set (0.00 sec)
ちゃんと、HIMITSU NO HOGEHOGE
が無視されて、HOGEHOGE
だけがヒストリーファイルに記録されてました。
$ cat ~/.mysql_history _HiStOrY_V2_ SELECT\040'HOGEHOGE'; exit
マニュアルにも書いてある
ソースから辿りましたが、マニュアルにもちゃんと記載がありました。
mysql ignores for logging purposes statements that match any pattern in the “ignore” list. By default, the pattern list is "IDENTIFIED:PASSWORD", to ignore statements that refer to passwords. Pattern matching is not case-sensitive. Within patterns, two characters are special: https://dev.mysql.com/doc/refman/8.0/en/mysql-logging.html