Rails 迁移似乎已完成,但 rake 仍将迁移显示为待处理

Rails migration appears completed, but rake still shows migration as pending

我 运行 在大型 MySql2 数据库上进行简单的 rails 迁移以将列添加到 table:

class AddMiddleNameToPerson < ActiveRecord::Migration[5.0]
  def change
    add_column :person, :middle_name, :string
  end
end

我在迁移过程中与 运行 应用 rails 应用程序的服务器断开连接。然后我重新连接并使用 bundle exec rake db:migrate:status 检查迁移状态,显示为关闭:

down    20170424182410  Add middle name to person

我想它还在后台 运行ning。所以我离开了一段时间,最终使用 rails 控制台我验证了 person.middle_name 可以在对象上访问。但是,db:migrate:status 仍然显示迁移失败,如果我再次尝试 运行 db:migrate,我会收到错误消息:

Mysql2::Error: Duplicate column name 'middle_name'

所以新列似乎在数据库中,并且可以通过 ActiveRecord 访问,但是 rake db:migrate:status 发现迁移是 down 并且 rake db:migrate 尝试重新 运行它,不成功。

如果这是一个生产数据库(或其他包含重要数据的数据库),那么不要 rake db:reset,因为那样会删除数据库,您将失去一切;另外 不要 db:migrate:down 因为那样会删除 middle_name 列,您将失去已有的任何中间名。

首先备份数据库或至少备份您正在使用的 table。

其次,使用 mysql CLI 工具连接到数据库并说 describe people;。您问题中的信息表明您会在其中看到 middle_name 列,但确保您连接到正确的数据库并没有什么坏处。如果 middle_name 不存在,那么您几乎可以肯定在某处连接到错误的数据库,如果存在,那么您只是需要清理迁移问题。

您说数据库连接在迁移完成前断开。迁移按以下顺序工作:

  1. 运行迁移更新数据库。
  2. schema_migrations table 中记录迁移的版本号。
  3. 重新生成 db/schema.rbdb/structure.sql

如果 1 完成但连接丢失,则 2 永远不会发生,因此迁移将有 运行 但 Rails 不会知道的。

如果没有其他环境需要迁移,那么您可以简单地删除迁移和 rake db:schema:dumprake db:structure:dump 以获得新的 schema.rbstructure.sql。迁移只是暂时的代码,可以让你从 A 到 B,所以在它们已经 运行 无处不在之后删除它们是好的(甚至推荐),长期重要的是你的数据库结构(在 db/schema.rbdb/structure.sql).

如果其他环境需要运行迁移那么您可以手动打补丁schema_migrations table;使用 mysql CLI 工具连接到数据库并说 insert into schema_migrations (version) values ('20170424182410');。 Rails 现在知道迁移是 运行 并且将来的 rake db:migrate 调用会很高兴。然后你想刷新你的schema.rbrake db:schema:dump)或structure.sqlrake db:structure:dump)。


您可能有一个 db/schema.rb 文件来跟踪您的数据库结构(包括 运行 的迁移版本号)。如果这样做,那么您将使用 rake db:schema:dump 重新生成它。如果你有 db/structure.sql 那么你会使用 rake db:structure:dump.