2012-03-08 2 views
9

Я хочу добавить индекс в производственную базу данных. К счастью, мы запускаем Postgres, что прекрасно позволяет одновременное индексирование, поэтому мы можем добавить индекс без простоев. Ловушки-параллельные индексы не могут быть добавлены из транзакции, а миграции рельсов переносят все внутри транзакции.Как остановить миграцию Rails 3.1 из транзакции?

К счастью, есть что-то похожее на очень простое решение: перезапишите закрытый метод ActiveRecord :: Migration ddl_transaction, как explained here.

class IndexUsersEmails < ActiveRecord::Migration 
    def ddl_transaction(&block) 
    block.call # do not start a transaction 
    end 

    def self.up 
    execute "CREATE INDEX CONCURRENTLY index_users_on_email ON users(email)" 
    end 
end 

Проблема в том, что она не работает в Rails 3.1. Я делаю именно то, что делает код в Gist, и рельсы, похоже, полностью игнорируют его. Любые идеи о том, куда идти с этим?

+0

Вы пробовали изменить определение метода, так что это метод класса? например 'def self.ddl_transaction (& block) ...' –

ответ

11

Я только заметил, что я никогда не принимал здесь ответ, поэтому я должен сказать, что я сделал. Оказывается, вы можете выйти из сделки, как это:

class AddFbPageIdIndexToTabs < ActiveRecord::Migration 
    def up 
    execute "END" 
    execute "CREATE INDEX CONCURRENTLY bob_lob_law_index ON bob_lob (law)" 
    execute "BEGIN" 
    end 

    def down 
    execute "END" 
    execute "DROP INDEX CONCURRENTLY bob_lob_law_index" 
    execute "BEGIN" 
    end 
end 

Просто запустите execute "END" перед вещью, которую вы хотите выполнить вне транзакции. Это закончит транзакцию, которую ActiveRecord :: Migration автоматически установит для миграции. После того, как вы закончите с кодом, который вы хотите запустить за пределами транзакции, execute "BEGIN" открывает новую транзакцию, чтобы ActiveRecord :: Migration мог пройти процесс очистки и закрыть транзакцию, которую он считает открытой.

(я забыл, где онлайн я нашел этот трюк, и не могу найти его сейчас. Правки добро пожаловать на источник этого!)

1

Я не говорю, что это «правильный путь» для этого, но то, что сработало для меня, заключалось в том, чтобы запустить только одну миграцию в изоляции.

rake db:migrate:up VERSION=20120801151807 

, где 20120801151807 это временная метка миграции CREATE INDEX одновременно.

По-видимому, он не использует транзакцию при выполнении одной миграции.