sql >> データベース >  >> RDS >> Mysql

utf8データはmysqlでは正常に見えますが、Railsでは壊れています

    MySQLクライアントがサーバーと対話する場合:

    1. サーバーは、テキストを単にバイトの文字列として受信します。クライアントは、そのようなテキストがどのようにエンコードされるかを以前に伝えているでしょう。

    2. サーバーがそのテキストをテーブルに格納する必要がある場合は、関連する列のエンコーディングにトランスコードする必要があります(異なる場合)。

    3. その後、クライアントがそのようなテキストを取得したい場合、サーバーはそれをクライアントが期待するエンコーディングにトランスコードする必要があります。

    手順1と3でクライアントが使用したエンコーディングが同じの場合 (これは通常、特に両方の場合のクライアントが同じアプリケーションである場合に当てはまります)、クライアントがそれが言ったもの以外のエンコーディングを使用している場合、それはしばしば見過ごされます。たとえば、クライアントがMySQLにlatin1を使用するように指示したとします。 、ただし実際にはutf8でデータを送信します :

    • 文字列'Jazz–Man' 0x4a617a7ae280934d616eとしてUTF-8でサーバーに送信されます 。

    • MySQLは、Windows-1252でこれらのバイトをデコードし、文字列'Jazz–Man'を表すと理解します。 。

    • utf8に保存するには 列、MySQLは文字列をUTF-8エンコーディングにトランスコードします0x4a617a7ac3a2e282ace2809c4d616e 。これは、SELECT HEX(name) FROM lessons WHERE id=79510を使用して確認できます。 。

    • クライアントが値を取得すると、MySQLはlatin1に値が必要であると判断します。 したがって、Windows-1252エンコーディング0x4a617a7ae280934d616eにトランスコードします。 。

    • クライアントはそれらのバイトを受信すると、それらをUTF-8としてデコードするため、文字列が'Jazz–Man'であると理解します。 。

    結論 :クライアントは何かが間違っていることに気づいていません。問題が検出されるのは、別のクライアント(UTF-8接続をlatin1と誤って記述していないクライアント)の場合のみです。 )テーブルを使用しようとします。あなたの場合、これはmysqldumpがデータのエクスポートを取得したときに発生しました。 --default-character-set=latin1 --skip-set-charsetを使用する オプションを使用すると、mysqldumpはアプリケーションと同じように壊れた方法で動作するようになり、正しくエンコードされたデータになりました。

    今後問題を解決するには、次のことを行う必要があります。

    1. MySQL接続文字セットを正しく設定するようにアプリケーションを構成します(例:set encoding: utf8 config/database.yml内 Railsの場合);

    2. データベース内のデータを再コーディングします。例: UPDATE lessons SET name = BINARY CONVERT(name USING latin1) (これは、誤ってエンコードされたすべてのテキスト列に対して実行する必要があることに注意してください)。

    また、これら2つのアクションをアトミックに実行することをお勧めしますが、これには多少の考慮が必要になる場合があります。



    1. IllegalStateException:データベースはすでに閉じられています(ViewPagerを使用)

    2. PDO_OCI-CLOBフィールドに

    3. 結合/サブクエリを適切に使用して複数のテーブルからデータを選択するにはどうすればよいですか? (PHP-MySQL)

    4. データベース管理者向けの15の基本的なMySQLインタビューの質問