sqlite3_backup *sqlite3_backup_init( sqlite3 *pDest, /* Destination database handle */ const char *zDestName, /* Destination database name */ sqlite3 *pSource, /* Source database handle */ const char *zSourceName /* Source database name */ ); int sqlite3_backup_step(sqlite3_backup *p, int nPage); int sqlite3_backup_finish(sqlite3_backup *p); int sqlite3_backup_remaining(sqlite3_backup *p); int sqlite3_backup_pagecount(sqlite3_backup *p);
備份 API 會將一個資料庫的內容複製到另一個資料庫。它可用於建立資料庫的備份,或將記憶體中的資料庫複製到永久檔案或從永久檔案複製到記憶體中。
另請參閱:使用 SQLite 線上備份 API
在備份作業期間,SQLite 會在目標資料庫檔案上保持寫入交易開啟。來源資料庫僅在讀取時才會被讀取鎖定;它不會在整個備份作業中持續鎖定。因此,可以在線上來源資料庫上執行備份,而不會阻止其他資料庫連線在備份進行時讀取或寫入來源資料庫。
要執行備份作業
sqlite3_backup_init(D,N,S,M) 的 D 和 N 參數分別是與目標資料庫相關聯的資料庫連線和資料庫名稱。資料庫名稱對於主資料庫是 "main",對於臨時資料庫是 "temp",或者對於附加資料庫是在 ATTACH 陳述式中 AS 關鍵字之後指定的的名稱。傳遞給 sqlite3_backup_init(D,N,S,M) 的 S 和 M 參數分別識別來源資料庫的資料庫連線和資料庫名稱。來源和目標資料庫連線(參數 S 和 D)必須不同,否則 sqlite3_backup_init(D,N,S,M) 將會失敗並返回錯誤。
如果目標資料庫上已經開啟了讀取或讀寫交易,則呼叫 sqlite3_backup_init() 將會失敗,返回 NULL。
如果在 sqlite3_backup_init(D,N,S,M) 中發生錯誤,則會返回 NULL,並且錯誤代碼和錯誤訊息會儲存在目標資料庫連線 D 中。可以使用 sqlite3_errcode()、sqlite3_errmsg() 和/或 sqlite3_errmsg16() 函式來擷取失敗呼叫 sqlite3_backup_init() 的錯誤代碼和訊息。成功呼叫 sqlite3_backup_init() 會返回一個指向 sqlite3_backup 物件的指標。sqlite3_backup 物件可以與 sqlite3_backup_step() 和 sqlite3_backup_finish() 函式一起使用來執行指定的備份作業。
函式 sqlite3_backup_step(B,N) 將在 sqlite3_backup 物件 B 指定的來源和目標資料庫之間複製最多 N 個頁面。如果 N 為負數,則會複製所有剩餘的來源頁面。如果 sqlite3_backup_step(B,N) 成功複製 N 個頁面並且還有更多頁面要複製,則該函式返回 SQLITE_OK。如果 sqlite3_backup_step(B,N) 成功完成從來源到目標的所有頁面的複製,則它返回 SQLITE_DONE。如果在執行 sqlite3_backup_step(B,N) 時發生錯誤,則會返回錯誤代碼。除了 SQLITE_OK 和 SQLITE_DONE 之外,呼叫 sqlite3_backup_step() 還可能返回 SQLITE_READONLY、SQLITE_NOMEM、SQLITE_BUSY、SQLITE_LOCKED 或 SQLITE_IOERR_XXX 擴展錯誤代碼。
sqlite3_backup_step() 可能會在以下情況下返回 SQLITE_READONLY:
如果 sqlite3_backup_step() 無法取得所需的檔案系統鎖定,則會呼叫忙碌處理函式(如果已指定)。如果忙碌處理函式在鎖定可用之前返回非零值,則會向呼叫者返回 SQLITE_BUSY。在此情況下,可以稍後重試呼叫 sqlite3_backup_step()。如果在呼叫 sqlite3_backup_step() 時,來源資料庫連線正用於寫入來源資料庫,則會立即返回 SQLITE_LOCKED。同樣,在此情況下,可以稍後重試呼叫 sqlite3_backup_step()。如果返回 SQLITE_IOERR_XXX、SQLITE_NOMEM 或 SQLITE_READONLY,則重試呼叫 sqlite3_backup_step() 沒有意義。這些錯誤被視為致命錯誤。應用程式必須接受備份操作已失敗,並將備份操作控制代碼傳遞給 sqlite3_backup_finish() 以釋放相關資源。
第一次呼叫 sqlite3_backup_step() 會取得目標檔案的獨佔鎖定。獨佔鎖定不會被釋放,直到呼叫 sqlite3_backup_finish() 或備份操作完成且 sqlite3_backup_step() 返回 SQLITE_DONE。每次呼叫 sqlite3_backup_step() 都會在來源資料庫上取得一個共享鎖定,該鎖定在 sqlite3_backup_step() 呼叫期間持續有效。由於來源資料庫在兩次呼叫 sqlite3_backup_step() 之間沒有被鎖定,因此來源資料庫可能會在備份過程中被修改。如果來源資料庫被外部程序或透過不同於備份操作所使用的資料庫連線修改,則備份將在下一次呼叫 sqlite3_backup_step() 時自動重新啟動。如果來源資料庫是使用與備份操作相同的資料庫連線修改的,則備份資料庫會同時自動更新。
當 sqlite3_backup_step() 返回 SQLITE_DONE 或應用程式希望放棄備份操作時,應用程式應該透過將 sqlite3_backup 傳遞給 sqlite3_backup_finish() 來銷毀它。sqlite3_backup_finish() 介面會釋放與 sqlite3_backup 物件相關聯的所有資源。如果 sqlite3_backup_step() 尚未返回 SQLITE_DONE,則目標資料庫上的任何作用中寫入交易都會被回滾。sqlite3_backup 物件在呼叫 sqlite3_backup_finish() 後即無效,且不得使用。
如果沒有發生 sqlite3_backup_step() 錯誤,則 sqlite3_backup_finish() 返回的值為 SQLITE_OK,無論 sqlite3_backup_step() 是否完成。如果在同一個 sqlite3_backup 物件上的任何先前 sqlite3_backup_step() 呼叫期間發生記憶體不足或 IO 錯誤,則 sqlite3_backup_finish() 會返回相應的錯誤碼。
sqlite3_backup_step() 返回 SQLITE_BUSY 或 SQLITE_LOCKED 不是永久性錯誤,且不會影響 sqlite3_backup_finish() 的返回值。
sqlite3_backup_remaining() 和 sqlite3_backup_pagecount()
sqlite3_backup_remaining() 常式會回傳在最近一次 sqlite3_backup_step() 結束時仍需備份的頁數。sqlite3_backup_pagecount() 常式會回傳在最近一次 sqlite3_backup_step() 結束時來源資料庫的總頁數。這些函式回傳的值只會由 sqlite3_backup_step() 更新。如果來源資料庫的修改方式會改變來源資料庫的大小或剩餘頁數,這些變更在下次 sqlite3_backup_step() 之前不會反映在 sqlite3_backup_pagecount() 和 sqlite3_backup_remaining() 的輸出中。
資料庫控制代碼的並行使用
在備份操作進行中或初始化時,應用程式可以將來源資料庫連線用於其他目的。如果 SQLite 已編譯並設定為支援執行緒安全的資料庫連線,則可以從其他執行緒並行使用來源資料庫連線。
但是,應用程式必須保證在呼叫 sqlite3_backup_init() 之後以及在對應的 sqlite3_backup_finish() 呼叫之前,目標資料庫連線不會傳遞給任何其他 API(由任何執行緒)。SQLite 目前不會檢查應用程式是否錯誤地存取目標資料庫連線,因此不會回報任何錯誤代碼,但操作仍可能發生錯誤。在備份進行中使用目標資料庫連線也可能導致互斥鎖死結。
如果在共享快取模式下執行,應用程式必須保證在備份執行期間不會存取目標資料庫使用的共享快取。實際上,這表示應用程式必須保證程序中的任何連線都不能存取正在備份的磁碟檔案,而不僅僅是傳遞給 sqlite3_backup_init() 的特定連線。
sqlite3_backup 物件本身是部分執行緒安全的。多個執行緒可以安全地對 sqlite3_backup_step() 進行多個並行呼叫。然而,嚴格來說,sqlite3_backup_remaining() 和 sqlite3_backup_pagecount() API 並非執行緒安全的。如果它們與另一個正在呼叫 sqlite3_backup_step() 的執行緒同時被呼叫,則它們可能會回傳無效的值。