« WebObjects:MySQLのためのEOModelの設定 | トップページ | WebObjects:メモリ不足エラー対応 »

MySQL:4.1日本語問題

MySQLは4.0から4.1のバージョンアップで日本語を含む文字コードの扱いが大きく変わっており,それが原因でデータベースで日本語テキストを読み書きするときに文字化けなどが発生するケースがあります。ここではその問題について,当方でわかっている範囲で簡単にまとめてみました。

この問題について,詳しくはMySQLユーザ会FAQページなどを参照してください。

MySQLの文字コード処理は何が変わったのか

MySQL4.1以前は,データベースに格納するテキストデータの文字コードを指定することはできましたが,MySQLがその指定に従って何らかの処理(文字コード変換など)をすることはなく,指定した文字コードは単なるラベルに過ぎなかったようです。
MySQL4.1以降では,指定した文字コードに基づいて次のような処理を行うようになりました。

データベースのスキーマ定義で指定された文字コードとクライアントツールで指定された文字コードが異なる場合,mysqldデーモンとクライアントとの間でデータ転送を行うときに,指定された文字コード間で文字コード変換を行います。
また,このときの文字コード変換は,一度Unicode(UCS-2)に変換してから目的の文字コードに再度変換するという手順になります。

それがどのような影響をもたらしているのか

1)日本語文字コードを指定して作成したデータベースのテキストフィールドに,コマンドラインツール「mysql」から文字コード指定なしでテキストデータを入力したとき,mysqlコマンドの文字コードのデフォルトが「latin1」なので,入力する日本語テキストに対して「latin1→日本語文字コード」の変換を行ってしまい,日本語テキストが壊れます。

2)mysqldデーモンで指定される文字コードのデフォルトが「latin1」なので,データベースを作成するときに文字コードを明示しないと,データベースやテキストフィールドの文字コードはlatin1となります。この状態でmysqlコマンドから日本語文字コードを指定してデータベースに日本語テキストを入力すると「日本語文字コード→latin1」の文字コード変換が起こりますが,latin1には日本語が含まれないため,日本語の文字がすべて「?」に置き換えられてデータベースに書き込まれます。

3)文字コード変換について,Unicodeと非Unicodeを変換する変換テーブルに標準がないため,文字コード変換を行うと一部の文字が意図せぬコードに変換されてしまう可能性があります。詳細はこちらとかこちらとかこちらを参照。なお,文字コード変換は一旦Unicode(UCS-2)に変換してから目的の文字コードに変換するため,非Unicodeから非Unicodeへの変換でもこの問題が発生します。

4)文字コードのデフォルトを変えずにデータベースをlatin1で作成しクライアントからlatin1で読み書きした場合,文字コードが同じなので文字コード変換は起こらずに日本語テキストをデータベースに保存・読み出しができます。ただし,コマンドラインツール「mysqldump」は文字コードのデフォルトが「UTF-8」のため,文字コードをデフォルトのままデータベースの内容をバックアップすると「latin1→UTF-8」の文字コード変換が起きてしまい,日本語テキストが壊れます。

5)JDBCアダプタを介してJavaアプリからデータベースを読み書きした場合,テキストデータはJavaのStringクラスで読み書きを行いますが,Stringクラスのテキストデータは内部でUCS-2で保持するので,データベースアクセスの際にテキストデータの文字コードとUCS-2との間でコード変換が発生するはずです。このときデータベースの文字コードがlatin1なら日本語テキストが壊れ,Unicode系でない場合はUnicodeと非Unicodeの不整合の問題が発生すると思われます。

どうすればいいのか

以下のような設定を行えば,問題は避けられるはずです。
1)MySQLのデータベースに設定する文字コード,及びMySQLに入出力するテキストデータの文字コードを1つに統一して,文字コード変換が起きないようにします。
2)JDBCアダプタからMySQLにアクセスする場合は,MySQLで使用するすべての文字コードにUnicode系を指定して,JavaのStringクラス(UCS-2)との間でUnicode系以外への文字コード変換が起きないようにします。

MySQLでデフォルトの文字コードを設定するには,設定ファイル「my.cnf」(Windowsの場合は「my.ini」)に文字コードの定義を追加します。
MySQLの設定ファイルについてはこちらを参照:[4.1][5.1]
ここで指定できる文字コードのリストはこちらを参照:[4.1][5.1]
Microsoftコードページ932「cp932」はMySQL4.1.12及び5.0.3以降で指定できます。

デフォルトの文字コードの変更については,ソースファイルのリコンパイルによる対応もありますが,mysqldumpについてはソースファイル上での指定にかかわらずUTF-8でリコンパイルされてしまうので,mysqldumpのデフォルト文字コードの変更についてはmy.cnfファイルで対応するしかありません。

my.cnfファイルの[mysqld]セクションで指定できるパラメータに「skip-character-set-client-handshake」があります。このパラメータはクライアントの文字コード設定をサーバの設定で上書きして文字コード変換を行わないようにするようです。この指定はMySQL4.1.15及びMySQL5.0.13以降で使えます。
また,文字コードに「binary」を指定してもMySQL4.1以前同様文字コード変換を行わなくなるようです。但し,データベースやテキストフィールドでbinary型を指定した場合は,テキストの検索や文字列長を指定して行う処理などで不都合が生じるようです。そのため,binaryの指定はクライアントツールに限ったほうがよいようです。

文字コードにUTF-8を指定したmy.cnfファイルの設定例:

[client]
default-character-set = utf8

[mysqld]
default-character-set = utf8
skip-character-set-client-handshake

[mysqldump]
default-character-set = utf8

[mysql]
default-character-set = utf8

注意:my.cnfファイルの設定を更新したら,MySQLを再起動する必要があります。

JDBCアダプタ(MySQL Connector/J)からMySQLにアクセスする場合は,JDBCアダプタがデータベースのクライアントとして動作するときの文字コードを指定しておきます。JDBCアダプタ文字コードはJDBC URLで指定します。
文字コードにUTF-8を指定する場合の設定例(文字コード以外の指定は省いています):
jdbc:mysql://ホスト名/データベース名?useUnicode=true&characterEncoding=UTF8
JDBC URLでのUTF-8設定について,詳細はこちらこちらを参照。

■関連情報
Microsoftコードページ932(Wikipedia
MySQLユーザ会/FAQページ

■関連書籍をAmazonで検索:[MySQL][JDBC]
MySQL徹底入門 第3版 ~5.5新機能対応~ (kindle版)

にほんブログ村 IT技術ブログへ にほんブログ村 IT技術ブログ プログラム・プログラマへ にほんブログ村 IT技術ブログ ネットワーク・SEへ 人気ブログランキングへ ←この記事が役に立ったという方はクリックお願いします。
ioPLAZA【アイ・オー・データ直販サイト】

|

« WebObjects:MySQLのためのEOModelの設定 | トップページ | WebObjects:メモリ不足エラー対応 »

JDBC」カテゴリの記事

MySQL」カテゴリの記事

サーバ管理」カテゴリの記事

プログラミング」カテゴリの記事

トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/505963/40079406

この記事へのトラックバック一覧です: MySQL:4.1日本語問題:

« WebObjects:MySQLのためのEOModelの設定 | トップページ | WebObjects:メモリ不足エラー対応 »