[前][次][番号順一覧][スレッド一覧]

mysql:13823

From: "Yoshinori Matsunobu" <"Yoshinori Matsunobu" <ymatsunobu@xxxxxxxxxx>>
Date: Mon, 26 Mar 2007 07:21:43 +0900
Subject: [mysql 13823] MySQLの現行UTF-8の問題とその対処方法について

松信です。

現時点で、MySQLの日本語問題の中で関心が高い項目である、
UTF-8 4バイト文字の扱いについて、
問題の内容、現時点で取れる対処法、およびMySQL ABが
計画している対処案(現行utf8の改良)を以下に記述します。
計画中の対処案については、将来のバージョンで実装されることは確実ですが、
強い要望またはコミュニティからの貢献が無い限り早期の対応は難しいです。
強い要望のある方は、直接私までお知らせ下さいますようお願い致します。

以下、長文ですがご了承ください。
※[mysql 13666][mysql 13812]とはスレッドを分けました。

●そもそもの問題
Windows Vistaから標準でサポートされるJIS X 0213:2004には、
UTF-8表現で4バイトとなる文字が存在します。
このような文字はMySQLのcharset utf8で定義した文字列型の列には入れることがで
きません。
MySQLのutf8は3バイト文字までしか対応していないためです。
不正な文字として扱われ(その意味でCESU-8とは異なると私は理解しています)、
「その4バイトのUTF-8の文字以降の全ての文字列が削除された上で格納される」
という動作をします。これは現時点の「仕様」と位置づけられています。

具体例:
mysql> CREATE TABLE t1 (c1 VARCHAR(30)) CHARSET utf8;
Query OK, 0 rows affected (0.17 sec)

# 0xF0909080 is 4byte UTF-8 character
mysql> INSERT INTO t1 VALUES(0xF0909080);
Query OK, 1 row affected, 1 warning (0.08 sec)

# "abc" + 4byte UTF-8 + "def"
mysql> INSERT INTO t1 VALUES(0x616263F0909080646566);
Query OK, 1 row affected, 1 warning (0.03 sec)

# "def" is truncated
mysql> SELECT HEX(c1) FROM t1;
+---------+
| HEX(c1) |
+---------+
|         |
| 616263  |
+---------+
2 rows in set (0.03 sec)

なおsql_mode='TRADITIONAL'などのstrictモードでは、エラーとなりINSERTされませ
ん。

▲入らない文字は何か
UTF-8 4バイトとなるJIS X 0213:2004文字は、以下で確認できます。
http://www.mysql.gr.jp/frame/modules/bwiki/index.php?utf8_4
ほかに、中国語の一部の文字などにも、4バイトとなる文字があります。
http://www.unicode.org/charts/PDF/U20000.pdf
このような文字を絶対に使わない、あるいは
禁則文字としてアプリケーションプログラムで弾く、といったことであれば
問題は発生しません。
以下はこのような文字を使うケースがあるとします。


●現時点での対応策
現時点では、「文字列型ではなくバイナリ型として列を定義する」ことでこの問題を
回避できます。
VARBINARY/BLOBとして定義するということです。
あるいはVARCHAR/TEXT CHARACTER SET binaryとして定義しても良いです。
(バイナリ型に変換されます)。
バイナリ型の列には、UTF-8の文字列(4バイトも含む)をそのまま入れ、
そのまま取り出すことができます。ただしバイナリ型は、
・1文字=1バイトとしてカウントされるので、CHAR_LENGTH()などが正しく機能しない
・バイナリ型の列にFULLTEXTインデックスを作ることはできない
・半角英字の大文字・小文字の区別がされる
・BINARY型(固定長バイナリ型)については、余剰分は0x00で埋められる
  http://dev.mysql.com/doc/refman/5.0/en/binary-varbinary.html
といった欠点/相違があるので注意してください。

先日のOSCでは、このほかの注意事項として、
「Connector/JなどではResultSet#getString()で
バイナリ型の列に入れたUTF-8値を読むと化けてしまうため、
getBytes()などを使う必要がある」と話しました(Connector/.NETも同様)。
これについては現在対応を進めていて、
早ければ次のコネクタのリリース版にでも、設定ファイルによってgetString()や
getObject()で
文字化けせずに取れる(文字列型に入れたUTF-8値と同じ感覚で使える)ようにする予
定です。

アプリ側の修正が不要(もしくは非常に少ない)な場合、
十分現実的な解決策になるのではないかと考えられます。
まずは、この対応策が取れるかどうかを検討して頂きたいと思います。
これでは問題があるという場合は、恒久的な対応策である、
「MySQL本体でUTF-8の4バイト対応をする」のを待つ、ということになります。


●計画している対処案
MySQL社内では、以下のような実装案を検討しています。

1.現行エンコーディングutf8(3バイト)を4バイトに拡張する。(残るのは新utf8)
2.現行エンコーディングutf8(3バイト)はそのまま残し、UTF-8 4バイト対応の新しい
エンコーディングutf8_4を追加する。
(残るのはutf8と新utf8_4)
3.現行エンコーディングutf8(3バイト)の名称をutf8_oldに変更する。そして
UTF-8 4バイト対応のエンコーディングutf8を追加する。(残るのはutf8_oldと新
utf8)
ステータス変数でどちらを使うかを切り替えられるようにし、同時に使えるのは片方
のみ
4.新しいエンコーディングutf16を導入する(残るのはutf8と新utf16)

森山さんご指摘のように、RFC3629ではUTF-8は4バイトまでで良くなっていることな
どから、
6バイトでなく4バイトで良いと考えています。

先日のOSCでは1と2について話をしましたが、実際には3と4も検討されています。
1が一番分かりやすいですが、既存環境との干渉が懸念されています。
2は、2つのUTF-8系エンコーディングが並立することになるので、
クライアントアプリ等でどちらを使うかを意識しないといけないなどの課題がありま
す。
吉岡さんのご指摘は、OSCでの私の説明を受けて、
2ではなく1を取るべき、とされたものです。
3は1と2の折衷案という位置づけです。

※「文字コード変換をしない場合に限り、不正な文字(4バイト UTF-8文字を含む)で
あっても
変換させずにそのまま格納するように、現行動作を変更する」という要望もあったの
ですが、
こちらはMySQLが本来意図している動作(=各文字エンコーディングのカバー範囲内の
文字だけを用いて
文字列比較やソートなどを行なう)を捻じ曲げるような実装になります。
簡単な実験で確認されている副作用だけでも、
・LIKE検索で、マッチするはずの結果がマッチしないことがある
・4バイトUTF-8は1文字ではなく4文字として扱われる
・ソートが正しく行なわれないことがある
といった問題があります。ほかにも出てくるかと思います。
そのため、不安定性を考えてこの実装は受け入れられない可能性が高いです。


●対応時期と要望について
UTF-4の4バイト文字対応について、対応することは確定していますが、
上記1〜4(または別の手段)のうちどの方法を用いるか、
またどのバージョンから導入するかについてはまだ検討中です。
現在はサポートしていないサロゲートペアを意識した処理が必要になることや、
InnoDBなどには1文字あたりのバイト数の最大値が3であることを前提とした実装部分
がある、
といった理由から、過去にcp932やeucjpmsを入れたときよりも影響範囲が大きいこと
は確実です。
それでも、1に比べれば、2〜4の方が既存環境への影響が少ないことから、
早期に導入できる可能性は高いと思います。

具体的な対応時期については、
この機能を切実に必要としているユーザー
(特にMySQL Enterpriseの現ユーザーと採用を検討しているユーザー)が
どの程度いるのか、に大きく依存することになりそうです。
要望が強ければ、優先度を上げて対応することができると思います。
私は、ユーザーにとってこの機能はどこまで必要性が高いのか、
日常的に使いそうもない文字ばかりだが本当に使うのか、
バイナリ型の利用では本当に受け入れられないのか、
といった具体的な事情を現時点では把握しきれていません。
この対応がなされない限りMySQLは使えない、といった
強い要望をお持ちの方は、私個人宛てでも結構ですので
・氏名
・所属会社名等
・(あれば)必要とされる具体的な理由
をお知らせいただけませんでしょうか?
また、実装(コーディングあるいはテスト等)に協力してくださる方がいれば、
早い段階で導入できる可能性はかなり高まると思うので、
そのような方がいらっしゃいましたらぜひご連絡頂ければ幸いです。


以上です。
----
松信 嘉範(MATSUNOBU Yoshinori)
Senior Consultant
MySQL AB, www.mysql.com


[前][次][番号順一覧][スレッド一覧]

->   13823 2007-03-26 07:21 ["Yoshinori Matsunobu] MySQLの現行UTF-8の問題とその対処方法について
     13826 2007-03-26 16:34 ┣[SUGAWARA Hajime <sug]                                       
     13827 2007-03-26 17:03 ┗[MORIYAMA Masayuki <m]