【发布时间】:2011-01-15 12:36:08
【问题描述】:
我在某处读到,要在 Python 中将数据保存到 SQLite3 数据库,应该调用连接对象的方法 commit。然而我从来不需要这样做。为什么?
【问题讨论】:
标签: python transactions sqlite autocommit
我在某处读到,要在 Python 中将数据保存到 SQLite3 数据库,应该调用连接对象的方法 commit。然而我从来不需要这样做。为什么?
【问题讨论】:
标签: python transactions sqlite autocommit
这意味着您的 SQLite3 数据库驱动程序以自动提交模式运行。
database transaction 是一个恢复单元。在事务性database engines 中,所有 SQL 语句都在数据库事务中执行。
当一条SQL语句没有包含在一对start-transaction(BEGIN或SAVEPOINT)和end-transaction(COMMIT、ROLLBACK或RELEASE)SQL语句中时,它会在由 SQL 语句的边界隐式分隔的数据库事务。据说 SQL 语句处于自动提交模式,因为它的数据库事务是自动分隔的。
当一条 SQL 语句包含在一对 start-transaction(BEGIN 或 SAVEPOINT)和 end-transaction(COMMIT、ROLLBACK 或 RELEASE)SQL 语句中时,它会在数据库事务显式由一对 SQL 语句分隔。据说该 SQL 语句处于手动提交模式,因为它的数据库事务是手动分隔的。
换句话说,在数据库引擎级别,自动提交模式是默认的。
最佳做法是always use the manual commit mode,因为通过将 SQL 语句显式分组到数据库事务中,可以避免数据损坏,因为恢复单元按预期分隔。
Database drivers 位于数据库引擎之上,因此可以转换它们发送到底层数据库引擎的 SQL 语句。数据库驱动程序通常在任何连接和结束事务(COMMIT 或 ROLLBACK)SQL 语句(即在任何尚未在数据库事务中的 SQL 语句之前说)。这样,喜欢使用自动提交模式的用户必须明确告诉数据库驱动程序。
换句话说,在数据库驱动程序级别,手动提交模式通常是默认的。
SQLite database engine 默认以自动提交模式运行:
测试自动提交模式
int sqlite3_get_autocommit(sqlite3*);如果给定的数据库连接处于或不处于自动提交模式,
sqlite3_get_autocommit()接口将分别返回非零或零。自动提交模式默认开启。BEGIN语句禁用自动提交模式。自动提交模式由COMMIT或ROLLBACK重新启用。如果多语句事务中的语句出现某些类型的错误(错误包括
SQLITE_FULL、SQLITE_IOERR、SQLITE_NOMEM、SQLITE_BUSY和SQLITE_INTERRUPT),则事务可能会自动回滚.判断SQLite是否在出错后自动回滚事务的唯一方法就是使用这个函数。如果另一个线程在该例程运行时更改了数据库连接的自动提交状态,则返回值未定义。
另请参阅对象、常量和函数列表。
PEP 249 要求 Python 数据库驱动程序默认以手动提交模式运行:
.commit()向数据库提交任何待处理的事务。
请注意,如果数据库支持自动提交功能,则必须 最初是关闭的。可以提供接口方法将其转回 开。
不支持事务的数据库模块应该实现 此方法具有 void 功能。
因此,SQLite3 database driver 默认以手动提交模式运行:
控制交易
底层
sqlite3库默认以自动提交模式运行,但Pythonsqlite3模块默认不运行。
autocommit模式表示修改数据库的语句立即生效。BEGIN或SAVEPOINT语句禁用autocommit模式,而COMMIT、ROLLBACK或RELEASE结束最外层事务,重新打开autocommit模式。Python
sqlite3模块默认发出BEGIN语句 隐式在数据修改语言 (DML) 语句之前(即INSERT/UPDATE/DELETE/REPLACE)。您可以通过
connect()调用的isolation_level参数来控制sqlite3隐式执行的BEGIN语句类型,或者 通过连接的isolation_level属性。如果您指定否isolation_level,使用普通的BEGIN,相当于 指定DEFERRED。其他可能的值为IMMEDIATE和EXCLUSIVE.您可以通过将
isolation_level设置为None来禁用sqlite3模块的隐式事务管理。这将使底层sqlite3库在autocommit模式下运行。然后,您可以通过在代码中显式发出BEGIN、ROLLBACK、SAVEPOINT和RELEASE语句来完全控制事务状态。在 3.6 版中更改:
sqlite3用于在 DDL 语句之前隐式提交打开的事务。现在已经不是这样了。
注意。 — 对于backwards compatibility reasons,SQLite3 数据库驱动程序仅在数据修改之前启动手动提交模式(INSERT、UPDATE、DELETE或REPLACE) SQL 语句,不在数据定义 (CREATE, DROP) 或数据查询 (SELECT) SQL 语句之前,它不是PEP 249 兼容和will hopefully be addressed soon。
以下 Python 程序说明了在 SQLite3 数据库驱动程序中使用手动提交模式与自动提交模式的含义:
import sqlite3
# Manual commit mode (the default).
connection = sqlite3.connect("test.sqlite")
cursor = connection.cursor()
cursor.execute("CREATE TABLE IF NOT EXISTS t (i INT)") # sent as is (DDL)
cursor.execute("INSERT INTO t VALUES (?)", (5,)) # sent as BEGIN; … (DML)
cursor.close()
connection.close() # connection closed without COMMIT statement (common error)
connection = sqlite3.connect("test.sqlite")
cursor = connection.cursor()
cursor.execute("SELECT * FROM t") # table persisted (full transaction)
assert cursor.fetchall() == [] # data did not persist (partial transaction)
cursor.close()
connection.close()
# Auto-commit mode.
connection = sqlite3.connect("test.sqlite", isolation_level=None)
cursor = connection.cursor()
cursor.execute("CREATE TABLE IF NOT EXISTS t (i INT)") # sent as is
cursor.execute("INSERT INTO t VALUES (?)", (5,)) # sent as is
cursor.close()
connection.close()
connection = sqlite3.connect("test.sqlite", isolation_level=None)
cursor = connection.cursor()
cursor.execute("SELECT * FROM t") # table persisted
assert cursor.fetchall() == [(5,)] # data persisted
cursor.close()
connection.close()
注意。 — 如果使用 in-memory 数据库而不是 on-disk 数据库(通过传递参数":memory:" 而不是"test.sqlite" 函数sqlite3.connect),因为当连接关闭时,内存中的数据库会被删除。
【讨论】:
可能自动提交已开启,默认为http://www.sqlite.org/c3ref/get_autocommit.html
【讨论】:
连接对象也可以用作自动提交或回滚事务的上下文管理器。 11.13.7.3. on docs.python
# Successful, con.commit() is called automatically afterwards
with con:
con.execute("insert into person(firstname) values (?)", ("Joe",))
【讨论】:
Python sqlite3 在“INSERT”或“UPDATE”之前自动发出 BEGIN 语句。之后它会自动提交任何其他命令或 db.close()
【讨论】:
添加isolation_level=None进行连接(Ref)
db = sqlite.connect(":memory:", isolation_level=None)
【讨论】:
sqlite." 是当前 Python 标准库的 sqlite3 模块的别名或等价物时,这只是明确告诉 sqlite3 应该打开自动提交模式,这是默认设置反正。默认情况下,它将conn.isolation_level 报告为'',但也不是非零会产生效果。