絵文字などを格納できるようにするため、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