开发者

Why would I ever want to revert a migration?

In Rails, migrations have a down method by default for reverting a migration. In what scenario would I ever want to revert a migration, though?

Some thoughts:

Whether in development or production, I always have a snapshot of my database to go back to, before I even run the migrations. Especially for migrations which perform data conversion, I find in most cases that reverting a snapshot is even faster than reverting a migration. (So I would never do it in a rush!)

If a migration were to fail, it would either:

  • fail with an exception on a non-transactional database, and thus leave the database broken, or
  • fail with an exception and roll back the transaction, and thus there would be no need to revert otherwise.

If the changes made are in production (or late in development), and later turn out to be a mistake, I would fix my 开发者_JS百科mistake in a new migration. I would not revert the old one. In development, I'd simply delete the migration.

I also find that the down method introduces extra code in which I repeat myself, and thus may introduce new bugs. This is against the DRY principle.

So I'm curious about the pros, because I can't think of any.


In development, it is easy and fast to incrementally "improve" migrations by using the down method automatically. Eg

  1. Create a migration and migrate to it
  2. Realize you need to make a change
  3. Migrate to the ver prior to your new migration by using db:migrate with a version
  4. Improve/fix your migration
  5. Rerun the migration task

Your method of taking snapshots works fine. But rails includes the same effect auto-magically using the "down" migration techniques. Works with all db's, tastes great

Added:

For production, I agree that a down migration shouldn't be needed. But sometimes mistakes happen and you need to roll back. The down migration path gives you a first, and quick opportunity to fix things in an emergency situation during an upgrade that goes wrong.

-- it is much faster to try a down migration in an emergency than to restore the db using a checkpoint.


The "down" migration used for DB Rollbacks is in place so that every action has an equal and opposite action. It takes the onus off of the developer to maintain database snapshots, and allows them to use code to achieve the same ends. As Larry K said, they're good for situations like so:

  • Add a database column called 'resubmitted', it's a boolean.
  • Product owner says they can resubmit multiple times, so change that column needs to be an int

Now, if you're 10 or 15 migrations deep, it's easier to just write a new one instead of losing all the dev data in the new tables/columns by doing a rollback. However, if you've just written that migration, it's cleaner and less cluttered to roll back, change the migration, and re-run it.

The other extremely useful feature of rollbacks is this:

  • Developer 1 has his own Dev DB. He writes a migration and runs it.
  • Developer 1 commits his migration to source control
  • Developer 2 has her own Dev DB. She writes a migration and runs it.
  • Developer 2 updates from source control
  • Developer 2 tries to run migrations but can't, as her local DB says "the latest migration has already been run", since her migration (the latest one), has technically already been run. Now she needs to rollback, then do a db:migrate to get all migrations in her local DB.


The idea of running a down migration in production horrifies me. Back when the preferred way to rollback all migrations was rake db:migrate VERSION=0 I would do this all the time in development. However, then I got paranoid that because it was committed to muscle memory I would accidentally type this on a production server when I meant to simply migrate.

Because of this paranoia, I add the following to all of my down methods.

  def self.down
    if Rails.env.production?
      raise ActiveRecord::IrreversibleMigration
    else
      drop_table :foo_bars
    end 
  end 

This way, it still works in development, but I can't accidentally nuke my production database from orbit while half-asleep at 2:00 AM.


When a migration hasn't had the expected result, it is better to roll back and rewrite it than to keep the failed migration in the code.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜