Docker MySQL でLOAD_FILE()を使うとNULLになる問題の解決方法。

3 min read読了の目安(約2300字

本記事は qrunch.net のサービス終了に伴い、2019-06-16 に投稿した自身の記事を移行したものです。

DockerでMySQL containerを立ち上げて LOAD_FILE() でINSERTしようとしたら、全てNULLになる問題に遭遇しました。

mysql> select hex(LOAD_FILE('/tmp/test.txt'));
+---------------------------------+
| hex(LOAD_FILE('/tmp/test.txt')) |
+---------------------------------+
| NULL                            |
+---------------------------------+
1 row in set (0.00 sec)

MySQL version

mysql> SELECT @@version;
+-----------+
| @@version |
+-----------+
| 8.0.16    |
+-----------+
1 row in set (0.00 sec)

Fileの権限などはOKでした。
MySQLは、secure_file_priv が設定されている場合、そのDirectoryにしかImport/Exportが出来ないようになります。
なので、確認してみます。

mysql> SHOW VARIABLES LIKE 'secure_file_priv';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| secure_file_priv | NULL  |
+------------------+-------+
1 row in set (0.00 sec)

うーん、Docker のMySQLのContainerのDefaultは NULLだ。
とりあえずググって色々出てきたのを一通り確認してもダメ。

mysql> SELECT 'aabb' INTO OUTFILE '/tmp/test.txt';
ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement

これが怪しい。
ということで、以下に変更して解決しました。

解決方法 / Solved it

% docker run --name mysql  -e MYSQL_ROOT_PASSWORD=mysql -d -p 3306:3306 mysql --secure-file-priv='/'

docker run に --secure-file-priv='/' を追加。
(※ 本番環境用には適した path を指定してください)

確認。

mysql> SHOW VARIABLES LIKE 'secure_file_priv';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| secure_file_priv | /     |
+------------------+-------+
1 row in set (0.00 sec)

これで取得出来ました。

mysql> SELECT hex(LOAD_FILE('/tmp/test.txt'));
+---------------------------------+
| hex(LOAD_FILE('/tmp/test.txt')) |
+---------------------------------+
| 616162620A                      |
+---------------------------------+
1 row in set (0.00 sec)

mysql>

secure_file_priv = NULL はダメみたいですね。(通常、何かしら設定されているので気がつかなかった)
ということで、公式Docの説明を見るとしっかり nullが設定されているとimport もexportも無効になる と書いてありました。

If set to NULL, the server disables import and export operations.

https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_secure_file_priv

これ、secure_file_priv = NULL だと 直感的にそのまま書いてあることを意味を捉えると
secure file privilege is null = 安全なファイル特権は無効 = import/exportが制限なし と逆の意味に捉える人が多い気がしますね。

ご注意ください。