Rails を utf8mb4 で動かす
絵文字などを格納できるようにするため、MySQL の encoding を utf8mb4 にすると、1文字が最大 4バイトになる。すると、primary key と unique key として使うカラムが、InnoDB の最大長 767バイトを超えるために、
ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes
というエラーが発生する。
それを乗り越えるための手順は以下の通り。
1) まず、my.cnf に以下を追加して restart させる。
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
innodb_file_per_table = 1 innodb_file_format = Barracuda innodb_large_prefix </code>
innodb_large_prefix が、767バイトを超えるキーを使うための設定。
collation として utf8mb4_unicode_ci と utf8mb4_general_ci の 2つが考えられるが、ここでは unicode_ci を選んだ。文字列の比較処理が拡張されていて、半角全角を同一とみなしてくれるなどの利点がある。その一方で、濁点などを区別しないという問題もある。
2) 次に、テーブルの ROW_FORMAT を変更する。Dynamic か Compressed にしないと、 innodb_large_prefix が効かない。
現状の ROW_FORMAT を確認すると、全部デフォルトの Compact になっている。
mysql> select row_format from information_schema.tables where table_schema='データベース名';
そこで、ROW_FORMAT を Dynamic に変更する。
mysql> ALTER TABLE テーブル名 ROW_FORMAT=DYNAMIC;
3) 新規に migration で作成されるテーブルの ROW_FORMAT を Dynamic にするため、
以下のコードを追加する(http://qiita.com/kamipo/items/101aaf8159cf1470d823)。
config/initializers/ar_innodb_row_format.rb
ActiveSupport.on_load :active_record do module ActiveRecord::ConnectionAdapters
class AbstractMysqlAdapter
def create_table_with_innodb_row_format(table_name, options = {})
table_options = options.reverse_merge(:options => 'ENGINE=InnoDB ROW_FORMAT=DYNAMIC')
create_table_without_innodb_row_format(table_name, table_options) do |td|
yield td if block_given?
end
end
alias_method_chain :create_table, :innodb_row_format
end
end end </code>
4) 既存のテーブルのエンコーディングを変換する
ALTER TABLE テーブル名 CONVERT TO CHARACTER SET utf8mb4;
参考 http://qiita.com/kamipo/items/101aaf8159cf1470d823 http://blog.kamipo.net/entry/2012/11/13/102024