如何阻止Rails 3.1迁移在事务中运行?

时间:2012-03-08 18:35:34

标签: ruby-on-rails rails-migrations

我想在生产数据库中添加索引。幸运的是,我们正在运行Postgres,它很好地允许并发索引,因此我们可以添加一个没有停机时间的索引。 catch - 并发索引无法从事务中添加,rails迁移会将事务内的所有内容都包装起来。

幸运的是,有些东西看起来像一个非常简单的解决方案:覆盖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中的代码执行操作,并且rails似乎完全忽略它。关于去哪里的任何想法?

2 个答案:

答案 0 :(得分: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 :(得分:1)

我并不是说这是“正确的方法”,但对我来说有用的只是孤立地进行一次迁移。

rake db:migrate:up VERSION=20120801151807

其中20120801151807是CREATE INDEX CONCURRENTLY迁移的时间戳。

显然,当您运行单个迁移时,它不会使用事务。