我在某处读到,要在 Python 中将数据保存到 SQLite3 数据库,commit
应该调用连接对象的方法。然而我从来不需要这样做。为什么?
5 回答
这意味着您的 SQLite3 数据库驱动程序以自动提交模式运行。
提交模式
数据库事务是一个恢复单元。在事务数据库引擎中,所有SQL 语句都在一个数据库事务中执行。
当一条 SQL 语句未包含在一对开始事务(
BEGIN
或SAVEPOINT
)和结束事务(COMMIT
或ROLLBACK
) SQL 语句中时,它将在由 SQL 语句边界隐式分隔RELEASE
的数据库事务中执行。据说 SQL 语句处于自动提交模式,因为它的数据库事务是自动分隔的。当一条 SQL 语句包含在一对开始事务 (
BEGIN
orSAVEPOINT
) 和结束事务 (COMMIT
,ROLLBACK
orRELEASE
) SQL 语句中时,它将在由这对 SQL 语句明确分隔的数据库事务中执行。据说 SQL 语句处于手动提交模式,因为它的数据库事务是手动分隔的。
换句话说,在数据库引擎级别,自动提交模式是默认的。
最佳实践是始终使用手动提交模式,因为通过将 SQL 语句显式分组到数据库事务中,可以避免数据损坏,因为恢复单元是按预期分隔的。
数据库驱动程序位于数据库引擎之上,因此可以转换它们发送到底层数据库引擎的 SQL 语句。数据库驱动程序通常通过在任何BEGIN
连接和结束事务(COMMIT
或ROLLBACK
)SQL 语句(也就是说,在任何尚未在数据库事务)。这样,喜欢使用自动提交模式的用户必须明确告诉数据库驱动程序。
换句话说,在数据库驱动程序级别,手动提交模式通常是默认的。
SQLite 数据库引擎
SQLite 数据库引擎默认以自动提交模式运行:
测试自动提交模式
int sqlite3_get_autocommit(sqlite3*);
如果给定的
sqlite3_get_autocommit()
数据库连接处于或不处于自动提交模式,则接口分别返回非零或零。自动提交模式默认开启。BEGIN
语句禁用自动提交模式。自动提交模式由 aCOMMIT
或重新启用ROLLBACK
。如果在多语句事务中的语句上发生某些类型的错误(错误包括
SQLITE_FULL
、SQLITE_IOERR
、SQLITE_NOMEM
、SQLITE_BUSY
和SQLITE_INTERRUPT
),则事务可能会自动回滚。判断 SQLite 是否在出错后自动回滚事务的唯一方法就是使用这个函数。如果在该例程运行时另一个线程更改了数据库连接的自动提交状态,则返回值未定义。
另请参阅对象、常量和函数的列表。
SQLite3 数据库驱动
PEP 249要求 Python 数据库驱动程序默认以手动提交模式运行:
.commit()
将任何挂起的事务提交到数据库。
请注意,如果数据库支持自动提交功能,则最初必须关闭。可以提供一个接口方法来重新打开它。
不支持事务的数据库模块应该使用 void 功能实现此方法。
因此,SQLite3 数据库驱动程序默认以手动提交模式运行:
控制交易
默认情况下,底层
sqlite3
库以自动提交模式运行,但 Pythonsqlite3
模块默认情况下不会。
autocommit
mode 表示修改数据库的语句立即生效。BEGIN
orSAVEPOINT
语句禁用autocommit
模式,结束最外层事务的aCOMMIT
、 aROLLBACK
或 a将重新打开模式。RELEASE
autocommit
默认情况下,Python
sqlite3
模块BEGIN
会在数据修改语言 (DML) 语句(即INSERT
/UPDATE
/DELETE
/REPLACE
)之前隐式发出语句。您可以通过调用的参数或连接的属性来控制隐式执行哪种
BEGIN
语句。如果您指定 no ,则使用纯文本,这等效于指定。其他可能的值为和 。sqlite3
isolation_level
connect()
isolation_level
isolation_level
BEGIN
DEFERRED
IMMEDIATE
EXCLUSIVE
您可以通过设置来禁用
sqlite3
模块的隐式事务管理。这将使底层库在模式下运行。然后,您可以通过在代码中显式发出、、和语句来完全控制事务状态。isolation_level
None
sqlite3
autocommit
BEGIN
ROLLBACK
SAVEPOINT
RELEASE
在 3.6 版更改:
sqlite3
用于在 DDL 语句之前隐式提交打开的事务。这已不再是这种情况。
笔记。— 出于向后兼容的原因,SQLite3 数据库驱动程序仅在数据修改(INSERT
、或)SQL 语句之前启动手动提交模式UPDATE
,而不是在数据定义(、)或数据查询()SQL 语句之前,这不符合 PEP 249并将希望很快得到解决。DELETE
REPLACE
CREATE
DROP
SELECT
例子
以下 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()
笔记。— 如果使用内存数据库而不是磁盘数据库(通过将参数":memory:"
而不是传递"test.sqlite"
给函数),第二个断言将失败sqlite3.connect
,因为在关闭连接时会删除内存数据库。
可能自动提交已打开,默认为http://www.sqlite.org/c3ref/get_autocommit.html
添加isolation_level=None
到连接(参考)
db = sqlite.connect(":memory:", isolation_level=None)
Python sqlite3 在“INSERT”或“UPDATE”之前自动发出 BEGIN 语句。之后,它会自动提交任何其他命令或 db.close()
连接对象也可以用作自动提交或回滚事务的上下文管理器。11.13.7.3。在 docs.python 上
# Successful, con.commit() is called automatically afterwards
with con:
con.execute("insert into person(firstname) values (?)", ("Joe",))