为什么Python的DB-API中的连接没有“begin”操作?
在使用mysql-python处理游标时,我以前会明确地调用“BEGIN;”、“COMMIT;”和“ROLLBACK;”这些命令,像这样:
try:
cursor.execute("BEGIN;")
# some statements
cursor.execute("COMMIT;")
except:
cursor.execute("ROLLBACK;")
然后,我发现底层的连接对象其实有对应的方法:
try:
cursor.connection.begin()
# some statements
cursor.connection.commit()
except:
cursor.connection.rollback()
查看了DB-API PEP后,我发现里面并没有提到连接对象的begin()方法,即使是扩展部分也没有。
顺便提一下,当你使用这个方法时,mysql-python会抛出一个弃用警告。而sqlite3.connection,比如说,根本就没有这个方法。
那么问题来了,为什么PEP里没有这个方法呢?这个语句是不是可以选择性使用,调用commit()就够了吗?
2 个回答
8
看看这个之前问过的问题。一般来说,处理事务的“流程”是这样的:
cursor = conn.cursor()
try:
cursor.execute(...)
except DatabaseError:
conn.rollback()
raise
else:
conn.commit()
finally:
cursor.close()
从 Python 2.6 开始,sqlite 的 Connection
对象可以作为上下文管理器使用,这样可以自动提交或回滚事务。
4
我决定自己回答一下:
在python-list上有一个关于DB API 2.0事务的讨论,还有一本很有名的书《SQL完全参考》中的一段话让我觉得,DB API实现了SQL1标准的行为:
SQL标准的第一个版本 (SQL1) 定义了一种隐式事务 模式,这种模式是基于早期DB2版本的事务 支持。在隐式模式下,只支持 COMMIT和 ROLLBACK语句。一个 SQL事务会在用户或程序执行的第一个SQL语句时自动开始, 并在执行COMMIT或ROLLBACK时结束。 一个事务的结束会隐式地 开始一个新的事务。
显式事务模式(SQL2和SQL:1999)在关系数据库管理系统(RDBMS)支持自动提交模式且当前连接处于该模式时似乎很方便,但DB API并没有反映这一点。