mysql2::错误:指定的密钥太长;对于只有87 db字段的表,最大密钥长度为767字节

31moq8wy  于 2021-06-17  发布在  Mysql
关注(0)|答案(3)|浏览(441)

我有一个包含87个db列的rails模型,但是当我尝试添加任何额外的db列时,它失败了

ArbitaryDatum.columns.count
 => 87

ArbitaryDatum.table_name
 => "arbitary_data"

ActiveRecord::Migration.add_column :arbitary_data, :attr51, :string

-- add_column(:arbitary_data, :attr51, :string)
   (1.4ms)  ALTER TABLE `arbitary_data` ADD `attr51` varchar(255)
Mysql2::Error: Specified key was too long; max key length is 767 bytes: ALTER TABLE `arbitary_data` ADD `attr51` varchar(255)
ActiveRecord::StatementInvalid: Mysql2::Error: Specified key was too long; max key length is 767 bytes: ALTER TABLE `arbitary_data` ADD `attr51` varchar(255)

我检查了我使用的mysql版本,

mysql --version
mysql  Ver 14.14 Distrib 5.5.62, for debian-linux-gnu (i686) using readline 6.3

我不明白为什么它不允许添加额外的表列
问。为什么我不能 Mysql2::Error: Specified key was too long

v64noz0r

v64noz0r1#

将数据库创建为utf8\u general\u ci,这样就没有问题了

8fq7wneg

8fq7wneg2#

在为这个问题奋斗了三天之后,@muistooshort在评论中说的一件事把我拉向了正确的解决方案。
你可能想在他的评论中重温你的数据库设计,这让我困扰了好几天。所需要的只是正确的方向(这在评论中)&我解决了这个问题。
注意:所提供的数据很少被用来隐藏项目模式结构。
我在添加新列时遇到问题,如错误日志中所述,但这不是由于在表中添加新列造成的。这是由于数据库中现有的表结构造成的。
我是在从 config/schema.rb 与索引一起创建相同的新表 arbitary_data_dup ```

replaced arbitary_data with arbitary_data_dup

ActiveRecord::Migration.create_table "arbitary_data_dup", force: :cascade do |t|
# code to add 87 columns for table
end

following index threw error

ActiveRecord::Migration.add_index "arbitary_data_dup", ["attr1", "arbitary_structure_id"], name: "index_arbitary_data_on_attr1_and_arbitary_structure_id", unique: true, using: :btree
ActiveRecord::Migration.add_index "arbitary_data_dup", ["attr1"], name: "index_arbitary_data_on_attr1", length: {"attr1"=>191}, using: :btree
ActiveRecord::Migration.add_index "arbitary_data_dup", ["id"], name: "index_arbitary_data_on_id", using: :btree
ActiveRecord::Migration.add_index "arbitary_data_dup", ["arbitary_structure_id"], name: "index_arbitary_data_on_arbitary_structure_id", using: :btree

在中运行上述代码时 `rails console` ,它抛出了相同的错误,我确定了它不允许添加新列的原因,

ActiveRecord::Migration.add_index "arbitary_data_dup", ["attr1", "arbitary_structure_id"], name: "index_arbitary_data_on_attr1_and_arbitary_structure_id", unique: true, using: :btree
-- add_index("arbitary_data_dup", ["attr1", "arbitary_structure_id"], {:name=>"index_arbitary_data_on_attr1_and_arbitary_structure_id", :unique=>true, :using=>:btree})
(52.5ms) CREATE UNIQUE INDEX index_arbitary_data_on_attr1_and_arbitary_structure_id USING btree ON arbitary_data_dup (attr1, arbitary_structure_id)
Mysql2::Error: Specified key was too long; max key length is 767 bytes: CREATE UNIQUE INDEX index_arbitary_data_on_attr1_and_arbitary_structure_id USING btree ON arbitary_data_dup (attr1, arbitary_structure_id)
ActiveRecord::StatementInvalid: Mysql2::Error: Specified key was too long; max key length is 767 bytes: CREATE UNIQUE INDEX index_arbitary_data_on_attr1_and_arbitary_structure_id USING btree ON arbitary_data_dup (attr1, arbitary_structure_id)

所以我找到了它不允许为现有索引添加新列->无效名称的原因。
所以我删除了索引,然后我可以添加新的列。

ActiveRecord::Migration.remove_index "arbitary_data", ["attr1", "arbitary_structure_id"]
-- remove_index("arbitary_data", ["attr1", "arbitary_structure_id"])
(148.6ms) DROP INDEX index_arbitary_data_on_attr1_and_arbitary_structure_id ON arbitary_data
-> 0.1698s
=> nil
ActiveRecord::Migration.add_column :arbitary_data, :attr51, :string
-- add_column(:arbitary_data, :attr51, :string)
(523.3ms) ALTER TABLE arbitary_data ADD attr51 varchar(255)
-> 0.5238s
=> nil

使用帮助再次添加了相同的索引
w6lpcovy

w6lpcovy3#

mysql在innodb中的前缀限制为767字节,在myisam中的前缀限制为1000字节,
不幸的是,没有真正的解决办法。您唯一的选择是减小列的大小,使用不同的字符集(如utf-8),或者使用不同的引擎(如myisam)。在本例中,我将字符集切换为utf-8,从而将最大密钥长度提高到255个字符。
将字符集迁移为utf8

reversible do |dir|
      dir.up {
        ActiveRecord::Migration.add_column :data, :attr51, "VARCHAR(255) CHARACTER SET utf8"
      }
    end

相关问题