在PostgreSQL中通过“ psycopg2”进行的事务是按游标还是按连接进行的?


10

我正在使用psycopg2数据库API 对PostgreSQL 9.3进行一些工作。

我将数据库API设置为最低隔离级别(“自动提交”模式),并且正在直接通过SQL管理自己的事务。例:

cur = self.conn.cursor()
cur.execute("BEGIN;")
cur.execute("SELECT dbId, downloadPath, fileName, tags FROM {tableName} WHERE dlState=%s".format(tableName=self.tableName), (2, ))
ret = cur.fetchall()
cur.execute("COMMIT;")

基本上,是由该事务启动的事务cur.execute("BEGIN;")仅限于该游标,还是整个连接(self.conn.cursor())?

我正在做的一些更复杂的事情涉及多个单独的数据库操作,这些操作我从逻辑上分解为功能。因为所有这些都在具有作为成员的连接的类中,所以在每个函数中创建游标要方便得多。但是,我不确定事务中创建游标的工作方式。

基本上,如果事务是按连接的,我可以在事务中即时创建大量游标。如果它们是每个光标,那意味着我必须在各处传递光标。哪有

文档没有涉及到这一点,尽管您可以打电话的事实connection.commit()使我相当有信心事务控制是针对每个连接的。

Answers:


7

事务是按会话(即每个连接)进行的。

PostgreSQL不支持挂起和恢复事务,因此psycopg2不能使它们成为每个游标,除非它在幕后隐式创建了新连接。

在实践中,我发现psycopg2的游标不是特别有用。如果您不使用从服务器获取的增量数据,它们可以保留结果集,但我认为它们没有其他好处。

为什么手动发出begincommit虽然,而不是使用它们的连接方法?


根据文档的AFICT,整个“ DB API”模型实际上根本不支持显式事务。
假名称

1
@FakeName不必显式begin。如果未打开任何事务,则将为您启动一个新事务。您只是commit描述事务。是的,DB-API模型确实支持显式事务。
克雷格·林格2014年

1
如果DB api在没有我专门指示的情况下自动执行此操作,那将是一个隐含的开始。此外,这无关紧要,因为(正如我在问题中所述),因为我不希望使用这些自动BEGIN语句,所以我正在使用自动提交模式。我不想psycopg2为每个创建新的交易SELECT
假名称

TL; DR基本上,我想知道所有事务的确切范围,因为A.我很疯狂,B。它对调试有很大帮助。
假名称

1
看到奇怪的错误突然冒出来,我不会感到惊讶。AFAIK自动提交实际上是要自动提交,而不是手动事务管理。如果您真的想手动管理事务范围,则多余的内容BEGIN是无害的,而PostgreSQL会忽略它WARNING: there is already a transaction in progress
Craig Ringer 2014年

1

psycopg2文档中:

在Psycopg中,事务由连接类处理。默认情况下,第一次将命令发送到数据库(使用连接创建的游标之一)时,会创建一个新事务。以下数据库命令将在同一事务的上下文中执行-不仅是第一个游标发出的命令,而且是由同一连接创建的所有游标发出的命令。如果任何命令失败,事务将中止,并且直到调用rollback()方法之前,将不执行其他命令。

同时,从2.4.2版开始,有一个autocommit属性(添加了强调):

读/写属性:如果为True,驱动程序将不处理任何事务,并且发送到后端的每个语句都将立即生效;如果False 在第一次执行命令时启动了新事务:必须手动调用方法commit()rollback()以终止事务。

自动提交模式对于执行需要在事务外部运行的命令很有用,例如CREATE DATABASEVACUUM

根据FalseDBAPI规范,默认值为(手动提交)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.