【发布时间】:2012-07-25 07:34:40
【问题描述】:
我使用的是 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 字节并且超过了 MySQL 对键的 767 字节的限制)。我也不需要它是 UTF-8,但数据库中的所有其他表都是 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阅读整个文件
所以我尝试将:limit => 100 添加到t.column 语句中,但我也没有成功使用此解决方案。问题是当原版已经到位时,我无法加载此补丁。换句话说 - 我的补丁加载 before 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 < 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
加载成功,但是在加载原来的ActiveRecord::SchemaMigration时会被覆盖。
我试图弄乱 ActiveSupport.on_load(:active_record) 但这似乎也不起作用。
有没有办法在原始 ActiveRecord::SchemaMigration 到位后加载此文件并使此补丁生效?
你有什么建议吗?如果这对您没有意义,我可以澄清这个问题的任何部分。尽管问我。我被这个问题困扰太久了。
【问题讨论】:
-
在做任何 Rails 工作之前,您是否考虑过手动创建
schema_migrations(包含合理的列大小)? -
是的,我已经考虑过了,但恐怕这不适用于
rake db:test:clone?此外,它会使生产服务器/开发人员机器上的设置复杂化,因为我必须运行一些脚本来预初始化数据库并创建此表。
标签: mysql ruby-on-rails activerecord rails-migrations