当前位置:  开发笔记 > 编程语言 > 正文

回滚失败的Rails迁移

如何解决《回滚失败的Rails迁移》经验,为你挑选了6个好方法。

如何回滚失败的rails迁移?我希望这rake db:rollback会撤消失败的迁移,但不会,它会回滚先前的迁移(失败的迁移减去一次).而且rake db:migrate:down VERSION=myfailedmigration也不起作用.我已经碰到了几次,这非常令人沮丧.这是我为复制问题所做的简单测试:

class SimpleTest < ActiveRecord::Migration
  def self.up
    add_column :assets, :test, :integer
    # the following syntax error will cause the migration to fail
    add_column :asset, :test2, :integer
  end

  def self.down
    remove_column :assets, :test
    remove_column :assets, :test2
  end
end

结果:

==  SimpleTest: migrating =====================================================
-- add_column(:assets, :test, :integer)
   -> 0.0932s
-- add_column(:asset, :error)
rake aborted!
An error has occurred, all later migrations canceled:

wrong number of arguments (2 for 3)

好吧,让我们回滚:

$ rake db:rollback
==  AddLevelsToRoles: reverting ===============================================
-- remove_column(:roles, :level)
   -> 0.0778s
==  AddLevelsToRoles: reverted (0.0779s) ======================================

是吧?这是我在SimpleTest之前的最后一次迁移,而不是失败的迁移.(哦,如果迁移输出包含版本号,那将会很好.)

因此,让我们尝试运行失败的迁移SimpleTest:

$ rake db:migrate:down VERSION=20090326173033
$

没有任何事情发生,也没有输出.但也许它还是进行了迁移?因此,我们修复SimpleTest迁移中的语法错误,并尝试再次运行它.

$ rake db:migrate:up VERSION=20090326173033
==  SimpleTest: migrating =====================================================
-- add_column(:assets, :test, :integer)
rake aborted!
Mysql::Error: Duplicate column name 'test': ALTER TABLE `assets` ADD `test` int(11)

不.显然迁移:down不起作用.它并没有失败,它只是没有执行.

除了手动进入数据库并删除它,然后运行测试之外,没有办法摆脱那个重复的表.必须有一个比这更好的方法.



1> Luke Francl..:

不幸的是,您必须手动清理MySQL的失败迁移.MySQL不支持事务数据库定义更改.

Rails 2.2包括PostgreSQL的事务性迁移.Rails 2.3包括SQLite的事务性迁移.

这对您现在的问题并没有真正的帮助,但如果您在将来的项目中可以选择数据库,我建议使用支持事务DDL的数据库,因为它使迁移更加愉快.

更新 - 这在2017年仍然如此,在Rails 4.2.7和MySQL 5.7上,Alejandro Babio在另一个答案中报告.



2> MarkusQ..:

要转到指定版本,只需使用:

rake db:migrate VERSION=(the version you want to go to)

但如果迁移失败,你必须先清理它.一种方法是:

编辑down迁移的方法,只是撤消那部分up工作

迁移回先前状态(您开始的地方)

修复迁移(包括撤消对您的更改down)

再试一次



3> Simon Woodsi..:

好的,大家好,这就是你实际做的方式.我不知道上面的答案在谈论什么.

    弄清楚向上迁移的哪个部分有效.评论那些.

    同时注释掉/删除破坏的部分迁移.

    再次运行迁移.现在它将完成迁移的未破坏部分,跳过已经完成的部分.

    取消注释在步骤1中注释掉的迁移位.

如果要验证您是否已立即恢复,则可以再次向下迁移并重新备份.


我做了一些非常相似的事情,但是我将第2步替换为"修复了破坏的部分迁移".

4> StefanH..:

我同意你应该尽可能使用PostgreSQL.但是,当您遇到MySQL时,可以通过首先在测试数据库上尝试迁移来避免大多数这些问题:

rake db:migrate RAILS_ENV=test

您可以恢复到之前的状态,然后重试

rake db:schema:load RAILS_ENV=test



5> Alejandro Ba..:

在2015年使用Rails 4.2.1和MySQL 5.7时,无法使用Rails提供的标准rake操作修复失败的迁移,就像在2009年一样.

MySql不支持回滚DDL语句(在MySQL 5.7手册中).并且Rails无法做任何事情.

此外,我们可以检查Rails如何完成工作:迁移包含在事务中,具体取决于连接适配器的响应方式:supports_ddl_transactions?.在rails source(v 4.2.1)中搜索此操作后,我发现只有Sqlite3和PostgreSql支持事务,默认情况下不支持.

编辑 因此,对原始问题的当前答案:必须手动修复失败的MySQL迁移.



6> BryanH..:

执行此操作的简单方法是将所有操作包装在事务中:

class WhateverMigration < ActiveRecord::Migration

 def self.up
    ActiveRecord::Base.transaction do
...
    end
  end

  def self.down
    ActiveRecord::Base.transaction do
...
    end
  end

end

正如Luke Francl指出的那样,"MySql [MyISAM表]不支持事务" - 这就是为什么你可能会考虑避免使用MySQL或特别是MyISAM.

如果您正在使用MySQL的InnoDB,那么上面的工作就可以了.任何向上或向下的错误都将退出.

要注意某些类型的操作无法通过事务还原.通常,无法回滚表更改(删除表,删除或添加列等).


这不是MyISAM或InnoDB的问题.InnoDB支持事务,但它不支持事务数据库定义(DDL)更改.在PostgreSQL中,您可以删除一个表,然后回滚该更改!
推荐阅读
罗文彬2502852027
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有