一尘不染

回滚失败的Rails迁移

mysql

如何回滚失败的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:迁移============================================= ========
-add_column(:assets,:test,:integer)
   -> 0.0932秒
-add_column(:asset,:error)
耙子流产了!
发生错误,所有后来的迁移都被取消:

错误的参数数量(2对3)

好的,让我们回滚一下:

$ rake db:rollback
== AddLevelsToRoles:还原============================================ ==
-remove_column(:roles,:level)
   -> 0.0778秒
== AddLevelsToRoles:恢复(0.0779s)=====================================

嗯?那是我在SimpleTest之前的最后一次迁移,而不是失败的迁移。(哦,如果迁移输出中包含版本号,那就太好了。)

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

$ rake db:migrate:down VERSION = 20090326173033
$

什么也没发生,也没有输出。但是也许它还是进行了迁移吗?因此,让我们修复SimpleTest迁移中的语法错误,然后尝试再次运行它。

$ rake db:migrate:up VERSION = 20090326173033
== SimpleTest:迁移============================================= ========
-add_column(:assets,:test,:integer)
耙子流产了!
Mysql :: Error:重复的列名'test':ALTER TABLE`assets` ADD`test` int(11)

不。显然,migrate:down无效。这不是失败,只是没有执行。

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


阅读 217

收藏
2020-05-17

共1个答案

一尘不染

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

Rails 2.2包括针对PostgreSQL的事务迁移。Rails 2.3包括SQLite的事务迁移。

这现在并不能真正解决您的问题,但是,如果您可以在将来的项目中选择数据库,我建议您使用支持事务性DDL的数据库,因为它使迁移更加轻松。

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

2020-05-17