見出し画像

【メモ】MySQL内のUTF-8のデータが文字化けしていたのを直す

はじめに

例の如くの備忘録です。
ある日、「MySQLのデフォルトの文字コードがlatin1になっていたのでUTF-8に変えたところ、Teampassからデータを見た時文字化けするようになってしまい、たぶんUTF-8でない文字コードでデータが保存されてると思うから原因を調べて欲しい」というお話がありました。
調べてみたところ、結果的にはTeampass側というよりはMySQL側の問題だったようです。
説明の都合上Teampassで利用しているテーブル名そのままの記述となっていますが、適宜自身の環境に合わせてDB名、テーブル名などを読み替えていただければと。
以下、調査手順。

手順

まあ何はともあれまずはDBを見に行きますか、ということでMySQL(MariaDB)のteampassデータベースにアクセスしてみます。

# mysql -u root -p  #mysqlに接続
MariaDB [(none)]> show databases;  #データベースの一覧を確認
MariaDB [(none)]> use teampass;  #teampassデータベースに接続
MariaDB [teampass]> show tables;  #テーブル一覧を確認
MariaDB [teampass]> select * from teampass_items\G  #各アイテムのレコードを確認

こうしてレコードを確認してみると、確かにlabelやdescriptionなどに『î』みたいな文字が入っているのが見えました。
ほうほうと思いつつ、もう少し詳しく調べてみます。

MariaDB [teampass]> show variables like '%char%';  #mysqlの文字コードを確認

+--------------------------+----------------------------+
| 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     | utf8                       |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+

MySQL全体の文字コードは基本的にutf8になっている様子。
個別に文字コードがどうなっているか掘り下げます。

MariaDB [teampass]> show columns from teampass_items;  #データ型の確認

+---------------------------+--------------+------+-----+---------+----------------+
| Field                     | Type         | Null | Key | Default | Extra          |
+---------------------------+--------------+------+-----+---------+----------------+
| id                        | int(12)      | NO   | PRI | NULL    | auto_increment |
| label                     | varchar(500) | NO   |     | NULL    |                |
| description               | text         | YES  |     | NULL    |                |
| pw                        | text         | YES  |     | NULL    |                |
| pw_iv                     | text         | YES  |     | NULL    |                |
| pw_len                    | int(5)       | NO   |     | 0       |                |
| url                       | varchar(500) | YES  |     | NULL    |                |
| id_tree                   | varchar(10)  | YES  |     | NULL    |                |
| perso                     | tinyint(1)   | NO   |     | 0       |                |
| login                     | varchar(200) | YES  |     | NULL    |                |
| inactif                   | tinyint(1)   | NO   |     | 0       |                |
| restricted_to             | varchar(200) | YES  | MUL | NULL    |                |
| anyone_can_modify         | tinyint(1)   | NO   |     | 0       |                |
| email                     | varchar(100) | YES  |     | NULL    |                |
| notification              | varchar(250) | YES  |     | NULL    |                |
| viewed_no                 | int(12)      | NO   |     | 0       |                |
| complexity_level          | varchar(3)   | NO   |     | -1      |                |
| auto_update_pwd_frequency | tinyint(2)   | NO   |     | 0       |                |
| auto_update_pwd_next_date | varchar(100) | NO   |     | 0       |                |
| encryption_type           | varchar(20)  | NO   |     | not_set |                |
+---------------------------+--------------+------+-----+---------+----------------+
20 rows in set (0.003 sec)

MariaDB [teampass]> ALTER TABLE teampass_items MODIFY description text CHARACTER SET utf8 COLLATE utf8_general_ci;  #descriptionカラムをUTF8に文字コードを変更してみる
Query OK, 0 rows affected (0.029 sec)
Records: 0  Duplicates: 0  Warnings: 0

更新できたレコードは0件。つまりdescriptionはみんなUTF-8っぽいです。
さらに調べてみます。

MariaDB [teampass]> show create table teampass_items\G  #create tableステートメントを確認

*************************** 1. row ***************************
      Table: teampass_items
Create Table: CREATE TABLE `teampass_items` (
 `id` int(12) NOT NULL AUTO_INCREMENT,
 `label` varchar(500) NOT NULL,
 `description` text DEFAULT NULL,
 `pw` text DEFAULT NULL,
 `pw_iv` text DEFAULT NULL,
 `pw_len` int(5) NOT NULL DEFAULT 0,
 `url` varchar(500) DEFAULT NULL,
 `id_tree` varchar(10) DEFAULT NULL,
 `perso` tinyint(1) NOT NULL DEFAULT 0,
 `login` varchar(200) DEFAULT NULL,
 `inactif` tinyint(1) NOT NULL DEFAULT 0,
 `restricted_to` varchar(200) DEFAULT NULL,
 `anyone_can_modify` tinyint(1) NOT NULL DEFAULT 0,
 `email` varchar(100) DEFAULT NULL,
 `notification` varchar(250) DEFAULT NULL,
 `viewed_no` int(12) NOT NULL DEFAULT 0,
 `complexity_level` varchar(3) NOT NULL DEFAULT '-1',
 `auto_update_pwd_frequency` tinyint(2) NOT NULL DEFAULT 0,
 `auto_update_pwd_next_date` varchar(100) NOT NULL DEFAULT '0',
 `encryption_type` varchar(20) NOT NULL DEFAULT 'not_set',
 PRIMARY KEY (`id`),
 KEY `restricted_inactif_idx` (`restricted_to`,`inactif`)
) ENGINE=InnoDB AUTO_INCREMENT=1343 DEFAULT CHARSET=utf8
1 row in set (0.161 sec)

MariaDB [teampass]> select TABLE_SCHEMA,TABLE_NAME,COLUMN_NAME from information_schema.COLUMNS where COLLATION_NAME like 'utf8%';  #UTF8のカラムを確認

~~中略~~
| teampass           | teampass_items                                     | label                      |
| teampass           | teampass_items                                     | description                |
| teampass           | teampass_items                                     | pw                         |
| teampass           | teampass_items                                     | pw_iv                      |
| teampass           | teampass_items                                     | url                        |
| teampass           | teampass_items                                     | id_tree                    |
| teampass           | teampass_items                                     | login                      |
| teampass           | teampass_items                                     | restricted_to              |
| teampass           | teampass_items                                     | email                      |
| teampass           | teampass_items                                     | notification               |
| teampass           | teampass_items                                     | complexity_level           |
| teampass           | teampass_items                                     | auto_update_pwd_next_date  |
| teampass           | teampass_items                                     | encryption_type            |
~~中略~~

やはりteampass_itemsの各カラムの文字コードはUTF-8。
これは別のところに原因がありそうだな、ということで調べてみたところ、こちらの記事が見つかりました。
どうやらこちらの文字化けはUTF-8で二重にエンコードされることで生じる文字化けのようです。
こちらの現象はmysql上でレコードの文字コードを変更しても改善しないことが多いので、一旦元の文字コードでdumpを取り、そのdumpの文字コードをutf8に変えてインポートするのが良いと。ふむふむ。

その通りに対応してみます。
元の文字コードはlatin1なのでlatin1でdumpを取得し、UTF-8でインポートします。

#teampassデータベース中のteampass_itemsテーブルのdumpをlatin1の文字コードで取得
# mysqldump -u root -p --skip-set-charset --default-character-set=latin1 teampass teampass_items > convert-dump.sql

#上記dumpの文字コードをutf8にしてteampassデータベースにインポート
# mysql -u root -p --default-character-set=utf8 -D teampass < convert-dump.sql

これで文字化けが無事解消されました!

いいなと思ったら応援しよう!

ピックアップされています

作業メモまとめ

  • 25本

コメント

コメントするには、 ログイン または 会員登録 をお願いします。
【メモ】MySQL内のUTF-8のデータが文字化けしていたのを直す|石灰/いしばい
word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word

mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1