Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails creating schema_migrations - Mysql2::Error: Specified key was too long

I am using Rails 3.2.6 and Mysql 6.0.9 (but I have exactly the same error on MySQL 5.2.25)

When I create new database (rake db:create) and then when I try to load the schema (rake schema:load) I get this error:

Mysql2::Error: Specified key was too long; max key length is 767 bytes: CREATE UNIQUE INDEX `unique_schema_migrations` ON `schema_migrations` (`version`)

After hours and hours of research I found these solutions:

1. Change MySQL variable innodb_large_prefix to true (or ON)

This didn't work. I tried it on my Linux server, my Mac and even on Windows - it just doesn't work.

2. Monkeypatch ActiveRecord::SchemaMigration.create_table

I do not need the version column to be 255 long (when it is UTF-8, then it takes 4*255 = 1020 bytes and exceeds the MySQL limit of 767 byte for keys). I do not need it to be UTF-8 either, but all other tables in the DB are UTF-8 and I have set utf8_czech_ci to be the default collation.

The method that actually creates the schema_migrations table looks like this:

def self.create_table
  unless connection.table_exists?(table_name)
    connection.create_table(table_name, :id => false) do |t|
      t.column :version, :string, :null => false
    end
    connection.add_index table_name, :version, :unique => true, :name => index_name
  end
end

You can read the whole file on Github rails/rails

So I tried to add :limit => 100 to the t.column statement, but I did not succeed with this solution either. The problem is that I cannot make this patch load when the originial is already in place. In other words - my patch loads before ActiveRecord::SchemaMigration so it is overwritten.

When I put this in config/initializers/patches/schema_migration.rb:

require 'active_record/scoping/default'
require 'active_record/scoping/named'
require 'active_record/base'

module ActiveRecord
  class SchemaMigration < ActiveRecord::Base
    def self.create_table
      unless connection.table_exists?(table_name)
        connection.create_table(table_name, :id => false) do |t|
          t.column :version, :string, :null => false, :limit => 100
        end
        connection.add_index table_name, :version, :unique => true, :name => index_name
      end
    end
  end
end

It is successfully loaded, but the it is overwritten when the original ActiveRecord::SchemaMigration is loaded.

I tried to mess up with ActiveSupport.on_load(:active_record) but that doesn't seem to work either.

Is there a way to load this file after the originial ActiveRecord::SchemaMigration is in place and make this patch work?

Do you have any suggestions? I can clarify any part of this question, if it makes no sense to you. Just ask me. I've been stuck with this for too long.

like image 859
Lukáš Voda Avatar asked Jul 25 '12 07:07

Lukáš Voda


2 Answers

767 key should work. Make sure you use utf8 encoding, and not utf16. I had same problem, and my mistake was that I accidently created utf16 database

like image 179
dpa Avatar answered Nov 10 '22 09:11

dpa


I suggest you to drop your database and recreate a new one with the following instructions :

 mysql -u root -p -e "CREATE DATABASE {DB_NAME} DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;"
like image 5
Tracy LOISEL Avatar answered Nov 10 '22 09:11

Tracy LOISEL