,我从OpenCongress一些奇怪的Postgres迁移代码和我得到这个错误:如何在Rails中启动事务而不启动事务?
RuntimeError: ERROR C25001 MVACUUM cannot run inside a transaction block
Fxact.c L2649 RPreventTransactionChain: VACUUM FULL ANALYZE;
所以我想尝试没有通过交易得到裹运行它。
,我从OpenCongress一些奇怪的Postgres迁移代码和我得到这个错误:如何在Rails中启动事务而不启动事务?
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
无法得到这个工作......但聪明的想法! – Crisfole 2012-11-29 17:07:06
鉴于我的原始帖子已超过三年,我不一定会期望这个工作了。 – 2013-01-29 21:00:41
我已经尝试了此页面上的大部分解决方案,但都没有成功。这[要点](https://gist.github.com/olivierlacan/ba81d56d3c9e2a506216)没有为Rails 3.2的工作。基本上通过'ddl_transaction'补丁结束/重新启动一个事务。 – 2015-02-16 22:07:03
以上回答是打破了Rails 3的作为ddl_transaction是进入ActiveRecord :: Migrator。我无法想出一个办法,以猴子打补丁类,所以这里是一个替代的解决方案:
我加下的lib文件/
module NoMigrationTransactions
def self.included(base)
base.class_eval do
alias_method :old_migrate, :migrate
say "Disabling transactions"
@@no_transaction = true
# Force no transactions
ActiveRecord::Base.connection.instance_eval do
alias :old_ddl :supports_ddl_transactions?
def supports_ddl_transactions?
false
end
end
def migrate(*args)
old_migrate(*args)
# Restore
if @@no_transaction
say "Restoring transactions"
ActiveRecord::Base.connection.instance_eval do
alias :supports_ddl_transactions? :old_ddl
end
end
end
end
end
end
然后你在你的迁移做的是:
class PopulateTrees < ActiveRecord::Migration
include NoMigrationTransactions
end
这样做是禁止交易时迁移类被加载(以前的不同加载希望后任何将来的加载之前),那么迁移之后,恢复旧的任何交易能力有。
任何人都可以确认这适用于rails〜> 3.2.6吗?我试过了,但没有效果。 – 2012-10-28 12:40:20
我并不是说这是做到这一点的“正确方法”,但对我而言,唯一的办法就是单独运行一次迁移。
rake db:migrate:up VERSION=20120801151807
其中20120801151807是迁移的时间戳。
显然,它在运行单个迁移时不使用事务。
哇,上述解决方案都没有工作,但这真的很有帮助。谢谢! – hurshagrawal 2012-12-21 16:42:37
由于这是hacky,因此增加了'commit;'到我的sql的开始为我工作,但这是为SQL Server,不知道这是否适用于postgres ...
例如:CREATE FULLTEXT INDEX ...
是sql-server用户事务内部是非法的。
so ...:
execute <<-SQL
commit;
create fulltext index --...yada yada yada
SQL
工作正常......我们稍后会看到我是否后悔。
这实际上是最hackish的所有我身边发现无法使用新的'disable_ddl_transaction方式:) – Flevour 2013-09-25 13:25:30
一个非常简单的,独立于Rails版本(2.3,3.2,4.0,无所谓)的方法是在迁移开始时简单地添加execute("commit;")
,然后编写SQL。
这立即关闭Rails的开始交易,并允许你写原始SQL,它可以创建自己的事务。在下面的例子中,我使用.update_all
和子查询LIMIT
处理更新一个庞大的数据库表。
举个例子,
class ChangeDefaultTabIdOfZeroToNilOnUsers < ActiveRecord::Migration
def self.up
execute("commit;")
while User.find_by_default_tab_id(0).present? do
User.update_all %{default_tab_id = NULL}, %{id IN (
SELECT id FROM users WHERE default_tab_id = 0 LIMIT 1000
)}.squish!
end
end
def self.down
raise ActiveRecord::IrreversibleMigration
end
end
现在有一种方法disable_ddl_transaction!
,允许这一点,如:
class AddIndexesToTablesBasedOnUsage < ActiveRecord::Migration
disable_ddl_transaction!
def up
execute %{
CREATE INDEX CONCURRENTLY index_reservations_subscription_id ON reservations (subscription_id);
}
end
def down
execute %{DROP INDEX index_reservations_subscription_id}
end
end
这应该是公认的答案! – 2015-06-19 13:22:45
请告诉更多的关于你正在运行的迁移,你的数据库如果它不是默认的mysql/sqlite的话,使用哪个适配器。这样我认为一个更有用的答案会跟随你的问题。 – Ariejan 2009-09-09 14:36:56
对不起,只是看到你在使用Postgres。 – Ariejan 2009-09-09 14:37:27
在这个特定迁移的情况下,我发现了'VACUUM'命令是不是真的有必要(它只做垃圾收集),以便消除这一呼吁的工作,但我还是想知道如何指导Rails的运行没有交易的迁移。 – hsribei 2009-09-12 15:19:02