PHP5から7へバージョンアップした時に発生した怪現象(?)です。
解決策(詳細は後述)
- mysqldumpにて文字コード:latin1でエクスポート
- エクスポートしたファイル内の"SET NAMES"の文字コードをutf8へ変更してインポート
前提
- Linux(CentOS7) + Apache + MariaDB + PHP
- 2015年にMinimalからインストールして構築しました
事象
- PHPのバージョンアップ後にDB文字化けが大発生しました、パニクりました
- Webアプリで表示されるDBデータが全て文字化け(なぜか文字化けしないテーブルもありました)
- MariaDB5から10へバージョンアップしてみましたが、ダメでした
- PHP5に戻すと、Webの文字化けはなおりました…
- 2017年に構築した同要件のWebサーバーは、同手順でPHPをバージョンアップしても、当事象は発生しませんでした
調査
そもそも、コンソール上でも文字化けしている
元々、コンソール上は文字化けしていた気も…ほとんどコンソール上でSQLのオペしないので…という言い訳
SELECT test_col FROM test_tbl LIMIT 1;
+-------------------------------------------------------+
| test_col |
+-------------------------------------------------------+
| a?†a?1a??c”¨a?1a?¬a??a?‰ |
+-------------------------------------------------------+
バイナリで表示したところ、やけに長い
文字コードはutf8、test_colの中は"テスト用スレッド"と入っているため24バイトのはずです。
SELECT test_col, HEX(test_col) FROM test_tbl LIMIT 1;
+-------------------------------------------------------+------------------------------------------------------------------------------------------------------------+
| test_col | hex(test_col) |
+-------------------------------------------------------+------------------------------------------------------------------------------------------------------------+
| a?†a?1a??c”¨a?1a?¬a??a?‰ | C3A3C692E280A0C3A3E2809AC2B9C3A3C692CB86C3A7E2809DC2A8C3A3E2809AC2B9C3A3C692C2ACC3A3C692C692C3A3C692E280B0
+-------------------------------------------------------+------------------------------------------------------------------------------------------------------------+
文字コード関連の環境変数を確認したところ、serverの文字コードがlatin1
SHOW VARIABLES LIKE '%char%';
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | utf8 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
clientの文字コードをlatin1にして再度表示したところ、文字化けが解消
SET NAMES latin1;
SELECT test_col, HEX(test_col) FROM test_tbl LIMIT 1;
+--------------------------+------------------------------------------------------------------------------------------------------------+
| test_col | hex(test_col) |
+--------------------------+------------------------------------------------------------------------------------------------------------+
| テスト用スレッド | C3A3C692E280A0C3A3E2809AC2B9C3A3C692CB86C3A7E2809DC2A8C3A3E2809AC2B9C3A3C692C2ACC3A3C692C692C3A3C692E280B0 |
+--------------------------+------------------------------------------------------------------------------------------------------------+
mysql latin1 utf8 文字化けなどで検索していると発見
https://www.gcd.org/blog/2009/09/177/
各文字をlatin1と判断されて、utf8でエンコードした文字列がDBに登録されていました。
解決策
mysqldumpにて文字コード:latin1でエクスポート
mysqldump -u root -p --default-character-set=latin1 test_db > test.sql
エクスポートしたファイル内の"SET NAMES"の文字コードをutf8へ変更してインポート
参考
https://qiita.com/tukiyo3/items/77c75f355e71d52e65f7
/etc/my.cnf.d/server.cnfの"[mysqld]"の下に以下を追加
/etc/my.cnf.d/server.cnf
character-set-server = utf8
mariaDB再起動
Webとコンソールで文字化けしないことを確認。