MySQL8系でutf8mb4なテーブルに4バイトのUnicode文字(例: 🍣🍺)があるとき、JetBrains系IDEやDataGripで確認すると ??
のように表示されていました。
一方、mysqlコマンドでは 🍣🍺 と正しく表示されていました。
そこで、JetBrains系IDEでも表示できるよう設定を変更したときのメモを残します。
目次
環境
- MySQL 8.0.33
- DataGrip 2023.1.2
- 今回はDataGripを使いますが、JetBrains系IDEのデータベースツールでも同じだと思います
- MySQL Connector/J 8.0.25
- DataGrip内部で使っているMySQLドライバー
再現
Docker Composeを使って再現してみます。
Docker Composeの準備
compose.ymlの作成
MySQL 8.0.33のイメージを使って環境を用意します。
また、文字コードの設定をするために my.cnf
を、テーブルの初期値を投入するために scripts
ディレクトリを、それぞれvolumesに指定しておきます。
services: db: image: mysql:8.0.33 container_name: mysql environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: test_db MYSQL_USER: foo MYSQL_PASSWORD: bar ports: - "13306:3306" volumes: - mysql-vol:/var/lib/mysql - ./my.cnf:/etc/mysql/conf.d/my.cnf - ./scripts:/docker-entrypoint-initdb.d volumes: mysql-vol:
my.cnfの作成
今回はすべて utf8mb4
にしておきます。
[mysqld] character-set-server=utf8mb4 collation-server=utf8mb4_bin [mysql] default-character-set=utf8mb4 [client] default-character-set=utf8mb4
scripts/init.sqlの作成
ホストの scripts
ディレクトリに init.sql
ファイルを用意します。
ここではテーブルの作成と、 🍣🍺 という値を持つ初期データの投入を行います。
CREATE TABLE articles ( id INT PRIMARY KEY AUTO_INCREMENT, memo VARCHAR(100) ) ENGINE=InnoDB; INSERT INTO articles (memo) VALUES ('🍣🍺');
Docker Composeの起動
$ docker compose up -d ... ⠿ Network mysql_utf8mb4_default Created ⠿ Volume "mysql_utf8mb4_mysql-vol" Created ⠿ Container mysql Started
動作確認
ログの確認
起動したら動作確認をします。
まずは、コンテナ名 mysql
のログを確認します。初期データの投入は成功したようです。
$ docker logs mysql ... 2023-07-12 13:19:00+00:00 [Note] [Entrypoint]: Creating database test_db 2023-07-12 13:19:00+00:00 [Note] [Entrypoint]: Creating user foo 2023-07-12 13:19:00+00:00 [Note] [Entrypoint]: Giving user foo access to schema test_db 2023-07-12 13:19:00+00:00 [Note] [Entrypoint]: /usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/init.sql ...
テーブルの確認
続いて、 mysql
コマンドを使ってテーブルの中身を確認していきます。
docker compose exec <service名> bash
を使ってコンテナに入り、mysqlコマンドを使用します。
$ docker compose exec db bash bash-4.4# mysql -ufoo -pbar -hlocalhost
character_set_***
関係を確認すると、 utf8mb4
になっていました。
mysql> show variables like '%char%'; +--------------------------+--------------------------------+ | Variable_name | Value | +--------------------------+--------------------------------+ | character_set_client | utf8mb4 | | character_set_connection | utf8mb4 | | character_set_database | utf8mb4 | | character_set_filesystem | binary | | character_set_results | utf8mb4 | | character_set_server | utf8mb4 | | character_set_system | utf8mb3 | | character_sets_dir | /usr/share/mysql-8.0/charsets/ | +--------------------------+--------------------------------+ 8 rows in set (0.00 sec)
続いて、初期値を入れたテーブルの中身を確認すると、🍣🍺が正しく保存されていそうでした。
mysql> use test_db mysql> show tables; +-------------------+ | Tables_in_test_db | +-------------------+ | articles | +-------------------+ 1 row in set (0.00 sec) mysql> select * from articles; +----+----------+ | id | memo | +----+----------+ | 1 | 🍣🍺 | +----+----------+ 1 row in set (0.00 sec)
DataGripでの確認
DataGripを開き、DataSourceとして MySQL
を選択します。
続いて、 compose.yml
などに従い、設定を行います。
準備ができたので、DataGripにて動作確認をします。
Query Consoleを開き、 show variables like '%char%';
を実行します。
すると、先ほどの mysql
コマンドの結果とは異なり、 character_set_results
が utf8mb3
になっていました。
続いて、テーブルを開いて中身を確認すると、冒頭の画像のように 🍣🍺 が ??
に差し替わっていました。
これで、 mysql
コマンドでは 🍣🍺 が表示されていたのにも関わらず、DataGripでは正しく表示されないことが再現できました。
対応
設定変更
DataGripを使い続けたいので方法を調べたところ、YouTrackに情報がありました。
Emojis are not displayed correctly - question marks ?? displayed instead. : DBE-17035
内容を見ると、 characterSetResults
を null
にすれば良さそうです。
そこで、DataGripのpropertyにある Advanced
タブを開き、 characterSetResults
を utf8
から null
に変更します。
動作確認
改めて、DataGripで動作確認を行います。
Query Consoleを開き、 show variables like '%char%';
を実行すると、 character_set_results
が空欄になっていました。
続いてテーブルを開いてみると、 🍣🍺 が表示されました。良さそうです。
ソースコード
再現するためのコードをGithubに上げました。
https://github.com/thinkAmi-sandbox/mysql_utf8mb4-example
プルリクはこちらです。
https://github.com/thinkAmi-sandbox/mysql_utf8mb4-example/pull/1