【MovableType, MySQL】記事中に BMP 外の文字を使う


100719-0001.png

Movable Type では最新の文字セットが使えない?

【Perl】文字化けしないメールの送り方」を書いていて気づいたのだが、Movable Type では記事中に BMP(基本多言語面)外の文字が使えない。といってもこれは MT 自体の責任ではなく、MySQL の現行リリース 5.1 では BMP 外の文字をサポートしないためだ。

The ucs2 and utf8 character sets do not support supplementary characters that lie outside the BMP.

ucs2utf8 というキャラクターセットは BMP 外にある追補された文字をサポートしません。

http://dev.mysql.com/doc/refman/5.1/en/charset-unicode.html

現在開発中の MySQL 5.5 ではこれが改善されて、BMP 外の文字を扱えるキャラクターセット utf8mb4utf16utf32 が追加された。

漢(オトコ)のコンピュータ道: 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.remora.cx
http://blog.remora.cx/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

VARCHARTEXT 類に収納できる文字数が減る。
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 𥧄

コメントを残す