[英]Why doesn’t SQLite3 require a commit() call to save data?
我在某處讀到要將數據保存到 Python 中的 SQLite3 數據庫,應該調用連接對象的方法commit
。 然而,我從來不需要這樣做。 為什么?
這意味着您的 SQLite3 數據庫驅動程序在自動提交模式下運行。
數據庫事務是一個恢復單元。 在事務數據庫引擎中,所有SQL 語句都在一個數據庫事務中執行。
當 SQL 語句沒有包含在一對開始事務( BEGIN
或SAVEPOINT
)和結束事務( COMMIT
、 ROLLBACK
或RELEASE
)SQL 語句中時,它將在由 SQL 語句的邊界隱式分隔的數據庫事務中執行。 據說 SQL 語句處於自動提交模式,因為它的數據庫事務是自動分隔的。
當 SQL 語句包含在一對開始事務( BEGIN
或SAVEPOINT
)和結束事務( COMMIT
、 ROLLBACK
或RELEASE
)SQL 語句中時,它將在由這對 SQL 語句顯式分隔的數據庫事務中執行。 據說 SQL 語句處於手動提交模式,因為它的數據庫事務是手動分隔的。
換句話說,在數據庫引擎級別,自動提交模式是默認的。
最佳實踐是始終使用手動提交模式,因為通過將 SQL 語句顯式地分組到數據庫事務中,可以避免數據損壞,因為恢復單元按預期分隔。
數據庫驅動程序高於數據庫引擎,因此可以轉換它們發送到底層數據庫引擎的 SQL 語句。 數據庫驅動程序通常通過在任何連接和結束事務( COMMIT
或ROLLBACK
)SQL 語句之后(即在任何 SQL 語句之前)向數據庫引擎隱式發送開始事務( BEGIN
)SQL 語句來強制執行手動提交模式。尚未在數據庫事務中)。 這樣,喜歡使用自動提交模式的用戶必須明確告訴數據庫驅動程序。
換句話說,在數據庫驅動程序級別,手動提交模式通常是默認的。
SQLite 數據庫引擎默認在自動提交模式下運行:
測試自動提交模式
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 數據庫驅動程序默認在手動提交模式下運行:
控制交易
底層的
sqlite3
庫默認以自動提交模式運行,但 Pythonsqlite3
模塊默認不運行。
autocommit
模式意味着修改數據庫的語句立即生效。BEGIN
或SAVEPOINT
語句禁用autocommit
模式,結束最外層事務的COMMIT
、ROLLBACK
或RELEASE
重新打開autocommit
模式。默認情況下,Python
sqlite3
模塊在數據修改語言 (DML) 語句(即INSERT
/UPDATE
/DELETE
/REPLACE
)之前隱式發出BEGIN
語句。您可以通過
connect()
調用的isolation_level
參數或連接的isolation_level
屬性來控制sqlite3
隱式執行哪種BEGIN
語句。 如果您未指定isolation_level
,則使用普通BEGIN
,這等效於指定DEFERRED
。 其他可能的值是IMMEDIATE
和EXCLUSIVE
。您可以通過將
isolation_level
設置為None
來禁用sqlite3
模塊的隱式事務管理。 這將使底層的sqlite3
庫在autocommit
模式下運行。 然后,您可以通過在代碼中顯式發出BEGIN
、ROLLBACK
、SAVEPOINT
和RELEASE
語句來完全控制事務狀態。在 3.6 版更改:
sqlite3
用於在 DDL 語句之前隱式提交打開的事務。 這已不再是這種情況。
筆記。 — 出於向后兼容的原因,SQLite3 數據庫驅動程序僅在數據修改( INSERT
、 UPDATE
、 DELETE
或REPLACE
)SQL 語句之前啟動手動提交模式,而不是在數據定義( CREATE
、 DROP
)或數據查詢( SELECT
)SQL 語句之前啟動不符合 PEP 249,有望很快得到解決。
以下 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
),則第二個斷言將失敗,因為在內存中當連接關閉時,數據庫將被刪除。
Python sqlite3 在“插入”或“更新”之前自動發出 BEGIN 語句。 之后它會自動提交任何其他命令或 db.close()
添加isolation_level=None
連接( Ref )
db = sqlite.connect(":memory:", isolation_level=None)
可能自動提交已開啟,默認情況下為http://www.sqlite.org/c3ref/get_autocommit.html
連接對象也可以用作自動提交或回滾事務的上下文管理器。 11.13.7.3。 在 docs.python 上
# Successful, con.commit() is called automatically afterwards
with con:
con.execute("insert into person(firstname) values (?)", ("Joe",))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.