Zero Downtime Rails Migrations with the Large Hadron Migrator Gem
Tuesday, April 9th, 2013
Are you working on a mature or legacy Rails app? If so, you know migrations that change the structure of your tables (like adding indices) or update many rows can be troublesome. You might be ask yourself, “Wow. I have this big app in production with lots of users and I have to perform an operation on the database…and I can’t afford to lock that table for an extended period of time? What should I do?”
Well, thanks to the good folks at Soundcloud, there is a solution. It’s called the “Large Hadron Migrator“.
Using this gem is simple. Like any Rails gem, you must first add it to your gemfile.
gem "lhm", "~> 1.1.0", :require => false
Be sure to run “bundle” at the command line. Once that’s done, create your migration file. In this example, I want to add an index to the user_id column in a table called “interests”. Here is how this migration might look:
require 'lhm' class AddUserIdIndexToInterestsTable < ActiveRecord::Migration def self.up Lhm.change_table :interests do |m| m.add_index [:user_id], "idx_user_id" end end def self.down Lhm.change_table :interests do |m| m.remove_index [:user_id], "idx_user_id" end end end
Note a couple of things different about this migration. First, you need to explicity require the Large Hadron Migrator gem with the “require ‘lhm'” line at the top. Second, you prefix your change_table method in the migration with “Lhm”. Why? Easy. To avoid data loss, the Large Hadron Migrator gem creates a temporary table during the migration. This avoids locking your normal table (and therefore forcing a shutdown of your app) during the migration.
Finally, run your migration like any other with…
rake db:migrate
And – presto! – the gem works its magic. It creates a temporary table, applies your changes, protects your data and you no longer have to lock your database table in a large app to perform structural changes, add indices or update lots of data.
Good times!
Not commented yet.