我从
OpenCongress运行一些奇怪的Postgres迁移代码,我收到这个错误:
- RuntimeError: ERROR C25001 MVACUUM cannot run inside a transaction block
- Fxact.c L2649 RPreventTransactionChain: VACUUM FULL ANALYZE;
所以我想尝试运行它,而不会被交易包裹.
解决方法
ActiveRecord :: Migration有以下私有方法,在运行迁移时被调用:
- def ddl_transaction(&block)
- if Base.connection.supports_ddl_transactions?
- Base.transaction { block.call }
- else
- block.call
- end
- end
正如你可以看到的,如果连接支持它,它会将迁移包装在一个事务中.
在ActiveRecord :: ConnectionAdapters :: PostgresqlAdapter你有:
- def supports_ddl_transactions?
- true
- end
sqlite 2.0及更高版本也支持迁移事务.
在ActiveRecord :: ConnectionAdapters :: sqliteAdapter你有:
- def supports_ddl_transactions?
- sqlite_version >= '2.0.0'
- end
那么,为了跳过交易,你需要以某种方式规避这一点.
这样的事情可能会起作用,虽然我还没有测试过:
- class ActiveRecord::Migration
- class << self
- def no_transaction
- @no_transaction = true
- end
- def no_transaction?
- @no_transaction == true
- end
- end
- private
- def ddl_transaction(&block)
- if Base.connection.supports_ddl_transactions? && !self.class.no_transaction?
- Base.transaction { block.call }
- else
- block.call
- end
- end
- end
然后,您可以按如下方式设置迁移:
- class SomeMigration < ActiveRecord::Migration
- no_transaction
- def self.up
- # Do something
- end
- def self.down
- # Do something
- end
- end