Postgres:cursor.execute("COMMIT") 与 connection.commit() 有何区别?
我正在运行一个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结束。