在PostgreSQL中重新启动一个失败的事务

通过事务我的意思是几个SQL语句包装(例如)在一个begin isolation level serializable块。 并发事务可以使这个事务失败,即回滚。

如何在PostgreSQL中重启失败的事务?

您需要使用客户端驱动程序特定的机制来检测事务中的错误。 当您看到错误时,您必须回滚事务重新发出整个事务 。 你不能只重新做最近的第一部分。

ROLLBACK是必需的; 如果您不这样做,则该连接的任何进一步操作都会失败,并显示“事务中止”错误。

大多数客户端驱动程序会引发exception(以支持它们的语言)来指示SQL错误,或者希望在每次数据库操作后检查错误代码,无论是通过检查函数返回代码还是通过调用特殊函数来检查错误。 node-postgres是asynchronous和非阻塞的,所以不会抛出exception; 您应该查找一个函数,让您查询会话的最后一个操作的结果SQLSTATE和客户端驱动程序的错误状态。

node-postgres 似乎没有丰富的文档,所以你最好的select可能是检查node-postgres的源代码,或find其他人如何做的例子。 我希望你会find函数来检查会话的错误状态。 你正在寻找的是一个函数来获取连接上的最后一个操作的SQLSTATE

可能值得一提的问题,特别是如何检测和处理node-postgres中的错误。


1实际上, SAVEPOINTROLLBACK TO SAVEPOINT让你做到这一点,但他们不会帮助序列化错误。

这个答案是在3年后join的,以此来说明以后的变化。 尽pipe原始答案仍然有效,但是这个答案显示了今天使用当时没有的正确工具是多么容易。


使用pg-promise很容易,它支持任何嵌套级别的嵌套事务。 请参阅嵌套事务 ,其中解释了顶层事务由标准BEGIN – > COMMIT / ROLLBACK ,而所有嵌套事务自动变为SAVEPOINT

 db.tx(t => { // BEGIN // top-level changes cannot be restarted: return t.any('UPDATE users SET name=$1 WHERE id=$2', ['Mike', 123]) .then(() => { return t.tx(t1 => { // SAVEPOINT return t1.none('INSERT log(event) VALUES($1)', 'entry'); }) .catch(error => { // ROLLBACK TO SAVEPOINT executed return t.none('UPDATE log SET event = $1'); }); }); }) .then(data => { // success, COMMIT executed }) .catch(error => { // error, ROLLBACK executed }); 

在上面的例子中,我们在顶层执行UPDATE ,因为这个原因无法重新启动。 然后我们使用INSERT执行一个嵌套的事务/保存点,如果失败,再次用顶层的UPDATE代替。

这样,即使我们的SAVEPOINT失败,我们仍然可以成功完成我们的顶级交易。

如果您希望能够重新启动整个事务,只需将整个事务包装到一个子事务中,然后您可以根据需要多次在主事务中重新运行事务。