创建schema_migrations的Rails – Mysql2 ::错误:指定的键太长了

我正在使用Rails 3.2.6和Mysql 6.0.9(但我在MySQL 5.2.25上有完全相同的错误)

当我创建新数据库( rake db:create )然后当我尝试加载模式( rake schema:load )时,我收到此错误:

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

经过数小时和数小时的研究,我发现了以下解决方

1.将MySQL变量innodb_large_prefix更改为true(或ON)

这没用。 我在我的Linux服务器,我的Mac甚至Windows上试过它 – 它只是不起作用。

2. Monkeypatch ActiveRecord :: SchemaMigration.create_table

我不需要version列长度​​为255(当它是UTF-8时,它需要4 * 255 = 1020字节并且超过了密钥的767字节的MySQL限制)。 我也不需要它是UTF-8,但DB中的所有其他表都是UTF-8,我已将utf8_czech_ci设置为默认排序规则。

实际创建schema_migrations表的方法如下所示:

 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 

您可以在Github rails / rails上读取整个文件

所以我试着在t.column语句中添加:limit => 100 ,但我也没有成功使用这个解决方案。 问题是,当原始版本已经到位时,我无法进行此补丁加载。 换句话说 – 我的补丁 ActiveRecord :: SchemaMigration 之前加载因此被覆盖。

当我把它放在config/initializers/patches/schema_migration.rb

 require 'active_record/scoping/default' require 'active_record/scoping/named' require 'active_record/base' module ActiveRecord class SchemaMigration  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 

它已成功加载,但在加载原始ActiveRecord :: SchemaMigration时会覆盖它。

我试图搞砸ActiveSupport.on_load(:active_record),但这似乎也不起作用。

有没有办法在原始的ActiveRecord :: SchemaMigration到位后加载这个文件并使这个补丁工作?

你有什么建议吗? 如果对你没有任何意义,我可以澄清这个问题的任何部分。 尽管问我。 我已经坚持了很久。

767键应该工作。 确保使用utf8编码,而不是utf16 。 我有同样的问题,我的错误是我意外地创建了utf16数据库

我建议您删除数据库并使用以下说明重新创建一个新数据库:

  mysql -u root -p -e "CREATE DATABASE {DB_NAME} DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;" 

我总是有这个错误,当它不是这个错误时:

Mysql2 ::错误:指定的密钥太长; 最大密钥长度为767字节:

就是这个:

Mysql2 ::错误:指定的密钥太长; 最大密钥长度为3072字节

所以我在这里建议我使用docker和官方mysql创建一个具有此设置的新数据库

 docker run -p 3306:3306 --name mysql-name -e MYSQL_ROOT_PASSWORD=name -d mysql:5.6 --innodb-large-prefix=1 --innodb-file-format=barracuda --innodb-file-per-table=1 

这里重要的不是docker是数据库啊配置

innodb-large-prefix = true innodb-file-format = barracuda innodb-file-per-table = true

最后如下的database.yml更改了utf8 latin1 sswedish是因为在服务器中我看到了:

 development: host: 192.168.99.100 database: name username: root password: root adapter: mysql2 charset: latin1 encoding: latin1 collation: latin1_swedish_ci test: host: 192.168.99.100 database: name_test username: root password: root adapter: mysql2 charset: latin1 encoding: latin1 collation: latin1_swedish_ci production: host: 192.168.99.100 database: name username: root password: root adapter: mysql2 charset: latin1 encoding: latin1 collation: latin1_swedish_ci 

之后工作

 bundle exec rake db:create bundle exec rake db:migrate 

我用猴子补丁做了这个,没有在这里建议的猴子补丁,它的工作原理

 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