我想在生产数据库中添加索引。幸运的是,我们正在运行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似乎完全忽略它。关于去哪里的任何想法?
答案 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迁移的时间戳。
显然,当您运行单个迁移时,它不会使用事务。