Movable Type では最新の文字セットが使えない?
「【Perl】文字化けしないメールの送り方」を書いていて気づいたのだが、Movable Type では記事中に BMP(基本多言語面)外の文字が使えない。といってもこれは MT 自体の責任ではなく、MySQL の現行リリース 5.1 では BMP 外の文字をサポートしないためだ。
The
ucs2
andutf8
character sets do not support supplementary characters that lie outside the BMP.
ucs2
とutf8
というキャラクターセットは BMP 外にある追補された文字をサポートしません。
現在開発中の MySQL 5.5 ではこれが改善されて、BMP 外の文字を扱えるキャラクターセット utf8mb4
、utf16
、utf32
が追加された。
漢(オトコ)のコンピュータ道: MySQLコミュニティ騒然!MySQL 5.5.4が与えるインパクト。
http://nippondanji.blogspot.com/2010/04/mysqlmysql-554.html
じゃあ、MySQL 5.5 へアップグレードしよう
これは結構な量になったので別記事に纏めた。
【MovableType, MySQL】MySQL 5.1 → 5.5 へのアップグレード | blog.delphinus.dev
https://blog.delphinus.dev/2010/07/mysql-5.1-5.5-upgrade.html
注意事項
公式サイトにも現行の utf8
から utf8mb4
へ変換するときのサポート情報がある。いくつか注意点を列挙してみよう。
MySQL :: MySQL 5.5 Reference Manual :: 9.1.11 Upgrading from Previous to Current Unicode Support
http://dev.mysql.com/doc/refman/5.5/en/charset-unicode-upgrading.html
VARCHAR
やTEXT
類に収納できる文字数が減る。- 1 文字当たり 3 バイトだった
utf8
と違い、utf8mb4
では 1 文字当たり 4 バイトになるため。 - インデックスされる最大文字数も減る。
- InnoDB では最大で 767 バイトがインデックスされる。これも
utf8mb4
にすることで 255 文字 → 191 文字に減る。 - パフォーマンスが落ちる。
- まあそりゃそうか。
- 4 バイトの UTF-8 に対応していない言語で困る。
- Perl は対応してるから関係ないや。
では実際に utf8mb4
へ変換してみよう。
変換作業
まずはサーバにログインする。
$ /usr/local/mysql/bin/mysql -uroot -p Enter password: mysql> use mt
記事の内容が納められているのは mt_entry
テーブルだ。その構成を確認する。
mysql> show create table mt_entry\G *************************** 1. row *************************** Table: mt_entry Create Table: CREATE TABLE `mt_entry` ( (中略) ) ENGINE=MyISAM AUTO_INCREMENT=643 DEFAULT CHARSET=utf8 1 row in set (0.00 sec) mysql> show table status from mt where Name = 'mt_entry\G *************************** 1. row *************************** Name: mt_entry Engine: MyISAM (中略) Collation: utf8mb4_general_ci Checksum: NULL Create_options: Comment: 1 row in set (0.00 sec)
テーブルのキャラクターセット(DEFAULT CHARSET
)と照合順序(Collation
)を変更する。
mysql> alter table mt_entry default character set utf8mb4, collate utf8mb4_general_ci; Query OK, 316 rows affected (0.06 sec) Records: 316 Duplicates: 0 Warnings: 0
テーブル内の各項目についても変更する。(長くなるので SQL 文として書いておく)
alter table mt_entry modify `entry_atom_id` varchar(191) CHARACTER SET utf8mb4 DEFAULT NULL ,modify `entry_basename` varchar(191) CHARACTER SET utf8mb4 DEFAULT NULL ,modify `entry_class` varchar(191) CHARACTER SET utf8mb4 DEFAULT 'entry' ,modify `entry_convert_breaks` varchar(30) CHARACTER SET utf8mb4 DEFAULT NULL ,modify `entry_excerpt` mediumtext CHARACTER SET utf8mb4 ,modify `entry_keywords` mediumtext CHARACTER SET utf8mb4 ,modify `entry_pinged_urls` mediumtext CHARACTER SET utf8mb4 ,modify `entry_tangent_cache` mediumtext CHARACTER SET utf8mb4 ,modify `entry_text` mediumtext CHARACTER SET utf8mb4 ,modify `entry_text_more` mediumtext CHARACTER SET utf8mb4 ,modify `entry_title` varchar(191) CHARACTER SET utf8mb4 DEFAULT NULL ,modify `entry_to_ping_urls` mediumtext CHARACTER SET utf8mb4 ;
このとき、varchar(255)
のままでは utf8mb4
への変更が出来なかったので、上記注意事項の通り 191 文字に変更したところうまくいった。これは InnoDB に限った注意点ではなかったのだろうか?
実際に BMP 外の文字を書いてみよう
BMP外のJIS第3・第4水準漢字 – faireal.net
http://deztec.jp/x/05/faireal/09-index.html
上記サイトに載っている漢字の一部をそのまま記事作成画面に貼り付けてみた。今までは“下書き保存”を押すと同時に消えてしまっていたのだが……
U+2000B ???? U+2123D ???? U+2131B ???? U+2146E ???? U+218BD ???? U+20B9F ???? U+216B4 ???? U+21E34 ???? U+231C4 ???? U+235C4 ???? U+2373F ???? U+23763 ???? U+23CFE ???? U+247F1 ???? U+2548E ???? U+2550E ???? U+25771 ???? U+259C4 ????
アレ?? やっぱりダメやん。いろいろ調べてみると、これは Movable Type 側の問題らしい。
*** mt/extlib/Data/ObjectDriver/Driver/DBI.pm.orig 2010-07-14 16:20:48.000000000 +0900 --- mt/extlib/Data/ObjectDriver/Driver/DBI.pm 2010-07-14 15:55:41.000000000 +0900 *************** *** 79,84 **** --- 79,85 ---- Carp::croak($@); } } + $dbh->do( "set names utf8mb4" ); if ($driver->reuse_dbh) { $Handles{$driver->dsn} = $dbh; }
このように書き換え、Apache、memcached を再起動すると正常に動くようになった。いつの間にか文字化けしてたので直しました。
U+2000B 𠀋 U+2123D 𡈽 U+2131B 𡌛 U+2146E 𡑮 U+218BD 𡢽 U+20B9F 𠮟 U+216B4 𡚴 U+21E34 𡸴 U+231C4 𣇄 U+235C4 𣗄 U+2373F 𣜿 U+23763 𣝣 U+23CFE 𣳾 U+247F1 𤟱 U+2548E 𥒎 U+2550E 𥔎 U+25771 𥝱 U+259C4 𥧄