docker-compose＋MySQL8（8.0.18）で初期データをCSVロードしようとするとエラー（The used command is not allowed with this MySQL version）に

# docker-compose＋MySQL8（8.0.18）で初期データをCSVロードしようとするとエラー（The used command is not allowed with this MySQL version）に

## 環境情報

- MacOS X 10.15.1（19B88）
- Docker 19.03.5
- MySQL 8.0.18

## docker-composeのディレクトリ構成

```shell-session
.
├── docker-compose.yml
└── mysql
    ├── init
    │   ├── 10_ddl.sql
    │   └── data.csv
```

## 各ファイルの中身

### docker-compose.ymlファイルの中身

```yaml
version: '3'
services:
  mysql:
    image: mysql:latest
    environment:
      #イメージの起動時に作成するデータベースの名前
      MYSQL_DATABASE: yudb
      #このユーザはMYSQL_DATABASE変数で指定されたデータベースに対してスーパーユーザとしての権限(GRANT ALL)を保持する
      MYSQL_USER: mysqluser
      #MYSQL_USERのパスワード
      MYSQL_PASSWORD: MySQLPass00
      # MySQLにおけるスーパーユーザであるrootアカウントに設定するためのパスワード
      MYSQL_ROOT_PASSWORD: MySQLRootPass00
    ports:
      - "3306:3306"
    volumes:
      #- ./mysql/var_lib_mysql:/var/lib/mysql　←　起動するたびにMySQLのデータベースを初期化したいのでコメントアウトしておく
      # /docker-entrypoint-initdb.d/配下は、Dockerコンテナが初回起動（初期化）される際に１度だけ実行されるスクリプトなどを配置
      # *.sh / *.sql / *.sql.gzの拡張子のファイルはファイル名の昇順に実行される。
      - ./mysql/init:/docker-entrypoint-initdb.d
```

### 10_ddl.sqlファイルの中身

```sql
create table if not exists m_sample(
  `code` char(3) not null,
  `name` varchar(80) not null,
  primary key(`code`)
) engine=innodb default charset=utf8;

LOAD DATA LOCAL INFILE '/docker-entrypoint-initdb.d/data.csv' INTO TABLE yudb.m_sample FIELDS TERMINATED BY ',' ENCLOSED BY '"';
```

### data.csvファイルの中身

```csv
"001","test001"
"002","test002"
"003","test003"
"004","test004"
```

## docker-composeでmysqlのコンテナを起動するとエラーが発生

`docker-compose up` コマンドを実行してコンテナを起動

```shell-session
$ docker-compose up -d
Creating network "docker-mysql8-err_default" with the default driver
Creating docker-mysql8-err_mysql_1 ... done
```

`docker-compose ps`コマンドを実行して状態を確認

```shell-session
$ docker-compose ps
          Name                        Command             State    Ports
------------------------------------------------------------------------
docker-mysql8-err_mysql_1   docker-entrypoint.sh mysqld   Exit 1
```

`docker-compose logs`コマンドを実行してログを確認

```shell-session
$ docker-compose logs
Attaching to docker-mysql8-err_mysql_1
mysql_1  | 2019-12-10 22:45:36+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.18-1debian9 started.
mysql_1  | 2019-12-10 22:45:36+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
mysql_1  | 2019-12-10 22:45:36+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.18-1debian9 started.
mysql_1  | 2019-12-10 22:45:36+00:00 [Note] [Entrypoint]: Initializing database files
mysql_1  | 2019-12-10T22:45:36.889727Z 0 [Warning] [MY-011070] [Server] 'Disabling symbolic links using --skip-symbolic-links (or equivalent) is the default. Consider not using this option as it' is deprecated and will be removed in a future release.
mysql_1  | 2019-12-10T22:45:36.889859Z 0 [System] [MY-013169] [Server] /usr/sbin/mysqld (mysqld 8.0.18) initializing of server in progress as process 44
mysql_1  | 2019-12-10T22:45:38.650792Z 5 [Warning] [MY-010453] [Server] root@localhost is created with an empty password ! Please consider switching off the --initialize-insecure option.
mysql_1  | 2019-12-10 22:45:42+00:00 [Note] [Entrypoint]: Database files initialized
mysql_1  | 2019-12-10 22:45:42+00:00 [Note] [Entrypoint]: Starting temporary server
mysql_1  | 2019-12-10T22:45:42.613856Z 0 [Warning] [MY-011070] [Server] 'Disabling symbolic links using --skip-symbolic-links (or equivalent) is the default. Consider not using this option as it' is deprecated and will be removed in a future release.
mysql_1  | 2019-12-10T22:45:42.614006Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.18) starting as process 93
mysql_1  | 2019-12-10T22:45:43.302666Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
mysql_1  | 2019-12-10T22:45:43.307378Z 0 [Warning] [MY-011810] [Server] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory.
mysql_1  | 2019-12-10T22:45:43.342347Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.18'  socket: '/var/run/mysqld/mysqld.sock'  port: 0  MySQL Community Server - GPL.
mysql_1  | 2019-12-10 22:45:43+00:00 [Note] [Entrypoint]: Temporary server started.
mysql_1  | 2019-12-10T22:45:43.361902Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Socket: '/var/run/mysqld/mysqlx.sock'
mysql_1  | Warning: Unable to load '/usr/share/zoneinfo/iso3166.tab' as time zone. Skipping it.
mysql_1  | Warning: Unable to load '/usr/share/zoneinfo/leap-seconds.list' as time zone. Skipping it.
mysql_1  | Warning: Unable to load '/usr/share/zoneinfo/zone.tab' as time zone. Skipping it.
mysql_1  | Warning: Unable to load '/usr/share/zoneinfo/zone1970.tab' as time zone. Skipping it.
mysql_1  | 2019-12-10 22:45:47+00:00 [Note] [Entrypoint]: Creating database yudb
mysql_1  | 2019-12-10 22:45:47+00:00 [Note] [Entrypoint]: Creating user mysqluser
mysql_1  | 2019-12-10 22:45:47+00:00 [Note] [Entrypoint]: Giving user mysqluser access to schema yudb
mysql_1  |
mysql_1  | 2019-12-10 22:45:47+00:00 [Note] [Entrypoint]: /usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/10_ddl.sql
mysql_1  | ERROR 1148 (42000) at line 7: The used command is not allowed with this MySQL version
```

ログを確認すると、ログの最終行に

```
mysql_1  | ERROR 1148 (42000) at line 7: The used command is not allowed with this MySQL version
```

というログが出力されていました。
調べてみると、MySQL8以降では、デフォルトのMySQLサーバーのままだと`LOAD DATA LOCAL INFILE`によるCSVファイルのロードが出来ないようです。

https://dev.mysql.com/doc/refman/8.0/en/load-data-local.html

## 解決方法

解決するには２つの対応が必要になります。
- １つはサーバーサイドの設定として`local_infile`システム変数をONにする
- もう１つがクライアントから接続する際に`--local-infile[=1]`オプションを指定する

#### サーバーサイドの設定で`local_infile`システム変数をON

`10_ddl.sql`ファイルに１行追加して以下のように定義する。
LOAD DATA LOCAL INFILEの行はコメントアウトして使えなくしておく。

```sql
set global local_infile = 1;

create table if not exists m_sample(
  `code` char(3) not null,
  `name` varchar(80) not null,
  primary key(`code`)
) engine=innodb default charset=utf8;

-- LOAD DATA LOCAL INFILE '/docker-entrypoint-initdb.d/data.csv' INTO TABLE yudb.m_sample FIELDS TERMINATED BY ',' ENCLOSED BY '"';
```
#### クライアントから接続する際に`--local-infile[=1]`オプションを指定する

これを実現するために、sqlファイルでのロードではなく、shellによるロードへ切り替えることで解消できました。
ディレクトリ構成は以下の通り。

```shell-session
.
├── docker-compose.yml
└── mysql
    └── init
        ├── 10_ddl.sql
        ├── 20_data_load.sh  ←  このファイルを追加
        └── data.csv
```

`20_data_load.sh`ファイルを追加します。

```shell
mysql -uroot -pMySQLRootPass00 --local-infile=1 yudb -e "LOAD DATA LOCAL INFILE '/docker-entrypoint-initdb.d/data.csv' INTO TABLE m_sample FIELDS TERMINATED BY ',' ENCLOSED BY '\"' LINES TERMINATED BY '\n'"
```

### 解消したか確認する

`docker-compose up -d`を実行後、しばらくしてから`docker-compose ps`を実行すると、今度は正常にMySQLのコンテナが起動していることがわかる。

```shell-session
$ docker-compose up -d
Creating network "docker-mysql8-err_default" with the default driver
Creating docker-mysql8-err_mysql_1 ... done


$ docker-compose ps
          Name                        Command             State                 Ports              
---------------------------------------------------------------------------------------------------
docker-mysql8-err_mysql_1   docker-entrypoint.sh mysqld   Up      0.0.0.0:3306->3306/tcp, 33060/tcp
```

念のためロードしたデータがちゃんと入っているかも確認してみる。

```shell-session
$ docker-compose exec mysql bash
root@46a05fff4d72:/#
root@46a05fff4d72:/# mysql -umysqluser -pMySQLPass00
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.18 MySQL Community Server - GPL

Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> connect yudb
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Connection id:    9
Current database: yudb

mysql> show tables;
+----------------+
| Tables_in_yudb |
+----------------+
| m_sample       |
+----------------+
1 row in set (0.00 sec)

mysql> select * from m_sample;
+------+---------+
| code | name    |
+------+---------+
| 001  | test001 |
| 002  | test002 |
| 003  | test003 |
| 004  | test004 |
+------+---------+
4 rows in set (0.00 sec)
```

とりあえずデータも無事にロードされているので、これでエラーの問題は解消できることがわかりました。