回滚失败的Rails迁移 [英] Rolling back a failed Rails migration
问题描述
如何回滚失败的Rails迁移?我希望rake db:rollback
会撤消失败的迁移,但是不会,它会回滚之前的迁移(失败的迁移减去一个).而且rake db:migrate:down VERSION=myfailedmigration
也不起作用.我已经遇到过几次了,这非常令人沮丧.这是我做的一个简单的测试,可以重现该问题:
How do you roll back a failed rails migration? I would expect that rake db:rollback
would undo the failed migration, but no, it rolls back the previous migration (the failed migration minus one). And rake db:migrate:down VERSION=myfailedmigration
doesn't work either. I've ran into this a few times and it's very frustrating. Here's a simple test I made to duplicate the problem:
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之前的最后一次迁移,而不是失败的迁移. (哦,如果迁移输出中包含版本号,那就太好了.)
huh? that was my last migration before SimpleTest, not the failed migration. (And oh, it would be nice if the migration output included the version number.)
因此,让我们尝试对失败的迁移SimpleTest进行停机:
So lets try running the down for the failed migration SimpleTest:
$ rake db:migrate:down VERSION=20090326173033
$
什么也没有发生,也没有输出.但是也许它还是进行了迁移吗?因此,让我们修复SimpleTest迁移中的语法错误,然后尝试再次运行它.
Nothing happens, and no output either. But maybe it ran the migration anyway? So lets fix the syntax error in the SimpleTest migration, and try to run it again.
$ 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)
不.显然,migrate:down无效.它没有失败,只是没有执行.
Nope. Obviously the migrate:down didn't work. It's not failing, it's just not executing.
除了手动进入数据库并删除它,然后运行测试之外,没有其他方法可以消除该重复表.有比这更好的方法了.
No way to get rid of that duplicate table other than manually going into the database and removing it, and then running the test. There's got to be a better way than that.
推荐答案
不幸的是,您必须手动清理MySQL失败的迁移. MySQL不支持事务数据库定义更改.
Unfortunately, you must manually clean up failed migrations for MySQL. MySQL does not support transactional database definition changes.
Rails 2.2包括针对PostgreSQL的事务性迁移. Rails 2.3包括针对SQLite的事务迁移.
Rails 2.2 includes transactional migrations for PostgreSQL. Rails 2.3 includes transactional migrations for SQLite.
这现在并不能真正解决您的问题,但是,如果您可以在将来的项目中选择数据库,我建议使用一个支持事务性DDL的数据库,因为它使迁移更加轻松.
This doesn't really help you for your problem right now, but if you have a choice of database on future projects, I recommend using one with support for transactional DDL because it makes migrations much more pleasant.
更新-在2017年的Rails 4.2.7和MySQL 5.7上仍然如此,这是Alejandro Babio在此处的另一个回答.
这篇关于回滚失败的Rails迁移的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!