Postgres:cursor.execute("COMMIT") 与 connection.commit() 有何区别?

6 投票
1 回答
7733 浏览
提问于 2025-04-18 05:32

我正在运行一个Postgres 9.2的服务器,并且有一个使用psycopg 2.5的Python客户端。

我做了一些测试,因为我在日志文件中看到很多 WARNING: there is no transaction in progress 的警告信息。

我有一些代码,可以简化成以下内容:

import psycopg2

connection = psycopg2.connect(...)
with connection.cursor() as cursor:
    # Multiple insert statements
    cursor.execute("INSERT INTO ...")

    cursor.execute("COMMIT")

我发现,如果我这样做,一旦第一次运行 COMMIT,因为我重用了同一个连接,所以上面的代码会被多次执行,之后的每个语句都会立即被提交。不过,如果我直接运行 connection.commit(),它就会按预期工作(提交到目前为止的语句,未来的语句不会自动提交)。

这是一个bug吗,还是我在这个过程中错过了什么细节?这是Postgres的问题,还是和psycopg2的内部机制有关?

提前谢谢你!

1 个回答

3

是的,这里有一个不太明显的区别(在DBAPI PEP和psycopg文档中都有说明)。所有符合Python DBAPI标准的适配器在通过连接发送第一个SQL语句时,都会自动开始一个事务。之后,你不应该直接执行回滚(rollback)或提交(commit),而是应该使用connection对象上提供的方法。

如果你想自己管理事务,只需将连接设置为自动提交模式,然后发送自己的BEGIN语句,接着是其他语句,最后用通常的COMMIT或ROLLBACK结束。

撰写回答