かなりユニークな状況で、私のチームは、データがlatin1としてエンコードされていると考えているデータベースにUTF-8バイトが含まれるようになりました。
少なくとも、私はこれが現在の状況であることを85%確信しています。
たとえば、 右側の単一引用符 は エンコーディングの概念がなかったプログラミング言語(Ruby 1.8) によってデータベースに渡され、データを未加工のバイト( 0xE2 0x80 0x99)。このデータは、私の知る限り(確認方法は?)、実際のバイトとして格納されていました。したがって、よりインテリジェントなプログラミング言語(Ruby 1.9)でデータが読み取られると、データベースは次のようにわかりやすく表示します "Oh!0xE2 is 'â'、0x80 is '€'、0x99 is '™'" =、「Mike's」の代わりに、「Mike’s」で終わります。これは、その値を選択するときにmysqlプロンプトで取得するものでもあります。
したがって、本質的に、データベースに保存されている一連のutf-8エンコードデータがあり、データはlatin1としてエンコードされていると見なされます。
これは、どういうわけかデータベースに「いいえ、あなたが何を考えていても、これは実際にはutf-8です」と伝えさせます。 CONVERT TO
は適切なツールのようには見えません。その場合、永続的な「マイク」が残ることになります。
私はこれに気づきました:
> SHOW VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR Variable_name LIKE 'collation%';
+--------------------------+-------------------+
| 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 |
| collation_connection | utf8_general_ci |
| collation_database | utf8_unicode_ci |
| collation_server | latin1_swedish_ci |
+--------------------------+-------------------+
そして、character_set_results
をlatin1
に変更すると、バイトが変換されず、utf8 OSでデータが適切に表示されると考えられます。
案の定、SET character_set_results=latin1;
は’
ではなく’
になります。涼しい!
それで、これを~/.my.cnf
に追加しました(これは、唯一のmy.cnfです。確認しました):
[mysqld]
...
character-set-results=latin1
mySQLプロンプトに戻ってcharacter_set_%
変数を確認しても、まだutf8
です。
はい、mysqld
がデーモンであることがわかりました。つまり、これを有効にするには、おそらくmysqlプロセス全体を再起動する必要があります。しかし、このマシンにMySQLをインストールした人は、brewの代わりにdmgを使用しました(私ではありませんでした)。MySQLの設定ペインでは、MySQLが実行されていないことが明らかに表示されています。ホール、私は実際のDBAに確認して、これがどれほどばかげているか、またはそれを行うためのより良い、よりクリーンな方法があるかどうかを確認したいと思います。
CONVERT TO
を使用してテーブル全体を切り替えるのは、いくつかの理由から悪いニュースです。 mysqlパフォーマンスブログで (概要:CONVERT TO
はtext
を変更する可能性がありますフィールドをmediumtext
に入力します)。
しかし、my.cnfの微調整でハッキングするよりも、実際にデータをutf8に変換する方が良いようです。
そのためには、
ALTER TABLE `t1`
MODIFY COLUMN `c1` text CHARACTER SET binary,
MODIFY COLUMN `c2` varchar(255) CHARACTER SET binary;
ALTER TABLE `t1`
DEFAULT CHARSET=utf8,
MODIFY COLUMN `c1` text CHARACTER SET utf8,
MODIFY COLUMN `c2` varchar(255) CHARACTER SET utf8;
データベース内のすべてのテーブルとその関連列。
機能:binary
エンコーディングに変更すると、MySQLは同じバイトを維持しますが、その意味は無視されます。次に、utf8
に切り替えても、バイトは同じままです。成功!
この変換により、これらのフィールドのFULLTEXTインデックスがすべて破壊されます(binary
エンコーディングはFULLTEXTインデックスをサポートしていません)。
私は これを自動化するbashスクリプト と書きました。 FULLTEXTインデックスの問題は処理されませんが、出発点としては適しています。
解決策はまったく同じではありませんが、 この質問 は、最初に同様の問題の方向性を見つけた場所であり、そこにある概念は、あなたが行きたいところへと連れて行ってくれるはずです。 MySQLはBINARY
文字セットを持ち、すべての外見からそれを変換することにより、MySQLが実際に行っていることを実現し、「役に立たない」ことを防ぐことができます。
Character_set_client = utf8のテストケース:
mysql> select CONVERT(CONVERT(CONVERT('Mike’s' USING latin1) USING binary) USING utf8);
+--------------------------------------------------------------------------------+
| CONVERT(CONVERT(CONVERT('Mike’s' USING latin1) USING binary) USING utf8) |
+--------------------------------------------------------------------------------+
| Mike’s |
+--------------------------------------------------------------------------------+
1 row in set (0.00 sec)
そのロジックを使用して、MySQLがutf8であると考える新しい列にデータを入力できます。