,我從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