2011-11-16 35 views
6

根據Postgres文檔 - 準備好後,事務可以稍後使用COMMIT PREPARED或ROLLBACK PREPARED分別提交或回滾。這些命令可以從任何會話中發出,not only the one that executed the original transaction.如何使PREPARE TRANSACTION工作

我試圖從CSV數據導入到數據庫表中,爲此,我現在用的是

COPY tablename [ (column [, ...]) ] FROM { 'filename' }

這一切都是在一個shell腳本來完成。 現在的問題是,我執行命令psql,並通過-c選項通過這個命令的參數(我通過命令

在命令prepare transaction 'some-id'開始交易)。

我想創建一個保存點並回滾它以避免任何錯誤。

後在shell腳本中一些其他的任務,我檢查錯誤,以前PSQL語句產生了,當我再嘗試使用命令

Prepared Rollback 'transaction-id'(在單獨psql command with sql statements

它回滾報告「No "transaction-id" found

我是否在概念錯誤或缺少過程中的東西?

發生這種情況是因爲我多次發出psql命令,並且每次都導致新的事務?

回答

8

爲了準備工作,COPYPREPARE必須在同一個會話中。因爲你的問題沒有具體的命令,我假設當你寫:

準備回滾「事務id」(與SQL語句分開psql的命令)

您正在使用不同的PSQL命令COPY和PREPARE。這是錯誤的。將COPY和PREPARE合併到同一個會話中。

E.g.

$ psql -c "BEGIN; COPY tablename FROM '/tmp/sql'; PREPARE TRANSACTION 'foobar';" db 
$ while /bin/not-ready-to-commit ; do sleep 1 ; done 
$ psql -c "COMMIT PREPARED 'foobar';" db 

PREPARE TRANSACTION作品寫當前事務刻錄到光盤,在當前會話中退出的交易過程。這就是爲什麼你需要一個BEGIN:它啓動你想要準備的交易。您希望受prepeare影響的所有命令都必須在事務啓動後發生(您的情況爲COPY命令)。當發行PREPARE TRANSACTION時,您當前所處的事務將使用您提供的標識符寫入磁盤。交易準備後發佈的任何聲明不再是交易的一部分。這樣做BEGIN; PREPARE... ; COPY運行沒有交易的COPY操作。

下面是PSQL殼爲例:

demo=# DELETE FROM foo; 
DELETE 4 
demo=# BEGIN; -- start a transaction 
BEGIN 
DEMO=# COPY foo FROM '/tmp/sql'; -- do what you want to commit later 
COPY 4 
demo=# PREPARE TRANSACTION 'demo'; -- prepare the transaction 
PREPARE TRANSACTION 
demo=# ROLLBACK; -- this is just to show that there is no longer a transaction 
NOTICE: there is no transaction in progress 
ROLLBACK 
demo=# SELECT * FROM foo; -- the table is empty, copy waiting for commit 
a | b 
---+--- 
(0 rows) 
demo=# COMMIT PREPARED 'demo'; -- do the commit 
COMMIT PREPARED 
demo=# SELECT * FROM foo; -- data is visible 
a | b 
---+--- 
1 | 2 
3 | 4 
5 | 6 
7 | 8 
(4 rows) 

編輯:您必須在PostgreSQL中啓用準備好的事務。CONF:

max_prepared_transactions = 1 # or more, zero (default) disables this feature. 

如果max_prepared_transactions爲零,PSQL報道,該交易ID沒有找到,但沒有就此發出警告功能被禁用。 Psql給出了PREPARE TRANSACTION的警告,但是如果你的shell腳本在prepare語句之後打印了東西,很容易就會漏掉。

3

PREPARE TRANSACTION分佈在多個交易服務器,通常由事務監視器或類似的應用程序服務器(例如EJB)使用。

在常規事務塊只需換您的副本:

START TRANSACTION; 
COPY ....; 
COMMIT; 

如果你想在中間的保存點,用SAVEPOINT some_name,然後你可以回滾到該保存點。

相關問題