2011-11-16 34 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,然后你可以回滚到该保存点。

相关问题