为什么Python的DB-API中的连接没有“begin”操作?

8 投票
2 回答
5657 浏览
提问于 2025-04-15 21:03

在使用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并没有反映这一点。

撰写回答