小巧、快速、可靠。
選擇三項。
交易

1. 交易控制語法

begin-stmt

BEGIN EXCLUSIVE TRANSACTION DEFERRED IMMEDIATE

commit-stmt

COMMIT TRANSACTION END

rollback-stmt

ROLLBACK TRANSACTION TO SAVEPOINT savepoint-name

2. 交易

除非在交易中,否則不會讀取或寫入。任何存取資料庫的指令(基本上是任何 SQL 指令,除了少數 PRAGMA 陳述式)如果尚未生效,將自動開始交易。自動開始的交易會在最後一個 SQL 陳述式結束時提交。

交易可以使用 BEGIN 指令手動開始。此類交易通常會持續到下一個 COMMIT 或 ROLLBACK 指令。但如果資料庫關閉或發生錯誤且指定 ROLLBACK 衝突解決演算法,交易也會 ROLLBACK。請參閱 ON CONFLICT 子句的文件,以取得有關 ROLLBACK 衝突解決演算法的其他資訊。

END TRANSACTION 是 COMMIT 的別名。

使用 BEGIN...COMMIT 建立的交易不會巢狀。對於巢狀交易,請使用 SAVEPOINTRELEASE 指令。語法圖表上方所示 ROLLBACK 指令的「TO SAVEPOINT name」子句僅適用於 SAVEPOINT 交易。嘗試在交易中呼叫 BEGIN 指令會失敗並產生錯誤,無論交易是由 SAVEPOINT 或先前的 BEGIN 開始的。COMMIT 指令和沒有 TO 子句的 ROLLBACK 指令對 SAVEPOINT 交易的工作方式與由 BEGIN 開始的交易相同。

2.1. 讀取交易與寫入交易

SQLite 支援來自不同資料庫連線(可能在不同的執行緒或程序中)的多個同時讀取交易,但僅支援一個同時寫入交易。

讀取交易用於僅讀取。寫入交易允許讀取和寫入。讀取交易由 SELECT 陳述式開始,而寫入交易由 CREATE、DELETE、DROP、INSERT 或 UPDATE 等陳述式開始(統稱為「寫入陳述式」)。如果在讀取交易處於活動狀態時發生寫入陳述式,則會在可能的情況下將讀取交易升級為寫入交易。如果其他資料庫連線已修改資料庫或已在修改資料庫的過程中,則無法升級為寫入交易,且寫入陳述式會失敗,並出現 SQLITE_BUSY

在讀取交易處於活動狀態時,由個別資料庫連線執行的任何資料庫變更,都不會被啟動讀取交易的資料庫連線看到。如果資料庫連線 X 持有讀取交易,則其他資料庫連線 Y 可能在 X 的交易仍開啟時變更資料庫的內容,但 X 在交易結束之前都無法看到這些變更。在讀取交易處於活動狀態時,X 將持續看到 Y 執行的變更之前的資料庫歷史快照。

2.2. 延遲、立即和獨佔交易

交易可以是延遲、立即或獨佔。交易的預設行為是延遲。

延遲表示交易並未實際開始,直到首次存取資料庫為止。在內部,BEGIN DEFERRED 陳述式僅設定資料庫連線上的旗標,關閉最後一個陳述式完成時通常會發生的自動提交。這會導致自動啟動的交易持續存在,直到明確的 COMMIT 或 ROLLBACK,或因錯誤或 ON CONFLICT ROLLBACK 子句而引發回滾為止。如果 BEGIN DEFERRED 之後的第一個陳述式是 SELECT,則會啟動讀取交易。後續寫入陳述式會在可能的情況下將交易升級為寫入交易,或傳回 SQLITE_BUSY。如果 BEGIN DEFERRED 之後的第一個陳述式是寫入陳述式,則會啟動寫入交易。

IMMEDIATE 會導致資料庫連線立即開始新的寫入,而不等待寫入陳述式。如果另一個寫入交易已在另一個資料庫連線中執行中,BEGIN IMMEDIATE 可能會失敗並傳回 SQLITE_BUSY

EXCLUSIVE 與 IMMEDIATE 類似,因為寫入交易會立即開始。在 WAL 模式 中,EXCLUSIVE 與 IMMEDIATE 相同,但在其他記錄模式中,EXCLUSIVE 會防止其他資料庫連線在交易進行中讀取資料庫。

2.3. 隱式與明確交易

隱式交易(自動開始的交易,而非由 BEGIN 開始的交易)會在最後一個活動陳述式完成時自動提交。陳述式會在其最後一個游標關閉時完成,這會在準備好的陳述式 重設完成 時發生。有些陳述式可能會在重設或完成之前「完成」交易控制,但無法保證這一點。確保陳述式已「完成」的唯一方法是對該陳述式呼叫 sqlite3_reset()sqlite3_finalize()。用於漸增 BLOB I/O 的開啟 sqlite3_blob 也會計為未完成的陳述式。sqlite3_blob 會在 關閉 時完成。

明確的 COMMIT 命令會立即執行,即使有待處理的 SELECT 陳述式。但是,如果存在待處理的寫入操作,COMMIT 命令會失敗並傳回錯誤碼 SQLITE_BUSY

如果另一個執行緒或處理程序有開啟的讀取連線,嘗試執行 COMMIT 也可能會導致 SQLITE_BUSY 回傳碼。當 COMMIT 以這種方式失敗時,交易仍保持活動狀態,並且可以在讀取器有機會清除後稍後重試 COMMIT。

在非常舊版本的 SQLite 中(3.7.11 版本之前 - 2012-03-20),如果存在任何待處理查詢,則 ROLLBACK 會失敗並顯示錯誤代碼 SQLITE_BUSY。在較新的 SQLite 版本中,ROLLBACK 會繼續執行,而待處理陳述式通常會中斷,導致它們傳回 SQLITE_ABORTSQLITE_ABORT_ROLLBACK 錯誤。在 SQLite 3.8.8 版本(2015-01-16)和更新版本中,只要 ROLLBACK 未修改資料庫架構,待處理讀取就會在 ROLLBACK 之後繼續運作。

如果 PRAGMA journal_mode 設為 OFF(因此停用回滾日誌檔案),則 ROLLBACK 命令的行為未定義。

3. 對交易中錯誤的回應

如果交易中發生某些類型的錯誤,則交易可能會自動回滾或不會自動回滾。可能導致自動回滾的錯誤包括

對於所有這些錯誤,SQLite 會嘗試只復原它正在處理的那一個陳述式,並讓同一個交易中先前陳述式的變更保持完整並繼續進行交易。但是,根據正在評估的陳述式和錯誤發生的時間點,SQLite 可能需要回滾並取消整個交易。應用程式可以使用 sqlite3_get_autocommit() C 語言介面來判斷 SQLite 採取哪種行動。

建議應用程式透過明確發出 ROLLBACK 命令來回應上述錯誤。如果交易已因錯誤回應而自動回滾,則 ROLLBACK 命令會失敗並顯示錯誤,但這不會造成任何損害。

未來版本的 SQLite 可能會擴充可能導致自動交易回滾的錯誤清單。未來版本的 SQLite 可能會變更錯誤回應。特別是,我們可能會在未來版本的 SQLite 中簡化介面,讓上述錯誤強制執行無條件回滾。

此頁面最後修改於 2023-03-14 14:31:07 UTC