SQLite 線程安全和併發

SQLite 與線程html

SQLite 是線程安全的。ios

線程模型git

SQLite 支持以下三種線程模型github

  • 單線程模型 這種模型下,全部互斥鎖都被禁用,同一時間只能由一個線程訪問。
  • 多線程模型 這種模型下,一個鏈接在同一時間內只有一個線程使用就是安全的。
  • 串行模型 開啓全部鎖,能夠隨意訪問。

設置線程模型sql

SQLite 能夠經過如下三種方式進行線程模型的設置,在實際應用中選擇任一一項均可以。數據庫

  • 編譯期設定 經過 SQLITE_THREADSAFE 這個參數進行編譯器的設定來選擇線程模型
  • 初始化設定 經過調用 sqlite3_config() 能夠在 SQLite 初始化時進行設定
  • 運行時設定 經過調用 sqlite3_open_v2() 接口指定數據庫鏈接的數據庫模型

SQLite 併發和事務緩存

事務安全

事務是 SQLite 的核心概念。對數據庫的操做 (絕大部分) 會被打包成一個事務進行提交,須要注意的是,這裏的打包成事務是自動開啓的。舉例而言,若是簡單在一個 for 循環語句裏向數據庫中插入 10 條數據,意味着將自動生成 10 個事務。但須要注意的是事務是很是耗時的,通常而言, SQLite 每秒可以輕鬆支持 50000 條的數據插入,可是每秒僅可以支持幾十個事務。通常而言,事務速度受限於磁盤速度。因此在批量插入時須要考慮禁用自動提交,將其用 BEGIN ... COMMIT 打包成一個事務。多線程

回滾模式和 WAL併發

爲了保證寫入正確,SQLite 在使用事務進行數據庫改寫時將拷貝當前數據庫文件的備份,即 rollback journal,當事務失敗或者發生意外須要回滾時則將備份文件內容還原到數據庫中,並同時刪除該日誌。這是默認的 DELETE 模式。

然後 SQLite 也引入了 WAL 模式,即 Write-Ahead Log。在這種模式下,全部的修改會寫入一個單獨的 WAL 文件內。這種模式下,寫操做甚至能夠不去操做數據庫,這使得全部的讀操做能夠在 "寫的同時" 直接對數據庫文件進行操做,獲得更好的併發性能。

鎖和併發

SQLite 經過五種鎖狀態來完成事務。

  • UNLOCKED ,無鎖狀態。數據庫文件沒有被加鎖。
  • SHARED 共享狀態。數據庫文件被加了共享鎖。能夠多線程執行讀操做,但不能進行寫操做。
  • RESERVED 保留狀態。數據庫文件被加保留鎖。表示數據庫將要進行寫操做。
  • PENDING 未決狀態。表示即將寫入數據庫,正在等待其餘讀線程釋放 SHARED 鎖。一旦某個線程持有 PENDING 鎖,其餘線程就不能獲取 SHARED 鎖。這樣一來,只要等全部讀線程完成,釋放 SHARED 鎖後,它就能夠進入 EXCLUSIVE 狀態了。
  • EXCLUSIVE 獨佔鎖。表示它能夠寫入數據庫了。進入這個狀態後,其餘任何線程都不能訪問數據庫文件。所以爲了併發性,它的持有時間越短越好。

一個線程只有擁有低級別鎖時纔可以得到更高一級的鎖

/*

** Lock the file with the lock specified by parameter eFileLock - one

** of the following:

**

**     (1) SHARED_LOCK

**     (2) RESERVED_LOCK

**     (3) PENDING_LOCK

**     (4) EXCLUSIVE_LOCK

**

** Sometimes when requesting one lock state, additional lock states

** are inserted in between.  The locking might fail on one of the later

** transitions leaving the lock state different from what it started but

** still short of its goal.  The following chart shows the allowed

** transitions and the inserted intermediate states:

**

**    UNLOCKED -> SHARED

**    SHARED -> RESERVED

**    SHARED -> (PENDING) -> EXCLUSIVE

**    RESERVED -> (PENDING) -> EXCLUSIVE

**    PENDING -> EXCLUSIVE

**

** This routine will only increase a lock.  Use the sqlite3OsUnlock()

** routine to lower a locking level.

*/

總結

綜上所述,要保證數據庫使用的安全,通常能夠採用以下幾種模式

  • SQLite 採用單線程模型,用專門的線程/隊列(同時只能有一個任務執行訪問) 進行訪問
  • SQLite 採用多線程模型,每一個線程都使用各自的數據庫鏈接 (即 sqlite3 *)
  • SQLite 採用串行模型,全部線程都公用同一個數據庫鏈接。

由於寫操做的併發性並很差,當多線程進行訪問時實際上仍舊須要互相等待,而讀操做所須要的 SHARED 鎖是能夠共享的,因此爲了保證最高的併發性,推薦

  • 使用多線程模式
  • 使用 WAL 模式
  • 單線程寫,多線程讀 (各線程都持有本身對應的數據庫鏈接)
  • 避免長時間事務
  • 緩存 sqlite3_prepare 編譯結果
  • 多語句經過 BEGIN 和 COMMIT 作顯示事務,減小屢次的自動事務消耗

參考

SQLite 是不是線程安全的

Using SQLite In Multi-Threaded Applications

SQLite在多線程環境下的應用

SQLite 插入太慢

SQLite 自動提交

YapDatabase wiki 詳解

 

https://blog.csdn.net/u011342466/article/details/79740086

相關文章
相關標籤/搜索