中止后如何重新开始交易?

How to restart transaction after abort?

我有这个代码:

for foo in range(1,10):
    try:
       cur_write = self.connection.cursor()
       cur_write.execute("SELECT raise_exception(foo)")
    
       connection.commit()
    except psycopg2.DatabaseError as ex:
       print "Failed to process: %s: %s", foo, ex

except 块第一次被正确击中,但第二次,我得到:

psycopg2.errors.InFailedSqlTransaction: current transaction is aborted, commands ignored until end of transaction block

但现在的问题是,我如何才能“重置”交易,因为我从未真正开始过交易?我稍后在代码中重用该连接。我必须重新连接吗?

Update 我通过将 commit 排除在循环之外解决了这个特殊问题,但我仍然很好奇如何通过保留 commit里面。

在SQL中,数据操作发生在事务中。交易通常以 BEGIN TRANSACTION 开始,以 COMMITROLLBACK 结束。这通常隐藏在像 psycopg2 这样的语言适配器中。医生说(强调我的):

In Psycopg transactions are handled by the connection class. By default, the first time a command is sent to the database (using one of the cursors created by the connection), a new transaction is created. The following database commands will be executed in the context of the same transaction – not only the commands issued by the first cursor, but the ones issued by all the cursors created by the same connection. Should any command fail, the transaction will be aborted and no further command will be executed until a call to the rollback() method.

所以恕我直言,唯一可靠的方法是在 except 分支中有一个 rollback 以正确关闭中止的事务并让下一个游标操作打开一个干净的新事务:

for foo in range(1,10):
    try:
       cur_write = self.connection.cursor()
       cur_write.execute("SELECT raise_exception(foo)")
    
       self.connection.commit()
    except psycopg2.DatabaseError as ex:
       print "Failed to process: %s: %s", foo, ex
       self.connection.rollback()             # cleanup the aborted transaction