Sqlite3 多線程訪問 讀寫鎖


Sqlite3 多線程訪問

Sqlite3 線程模式

sqlite3有三種線程模式,在編譯時開啟宏SQLITE_THREADSAFE=0/1/2來設置編譯支持,
sqlite3_config(SQLITE_CONFIG_SINGLETHREAD/SQLITE_CONFIG_SERIALIZED/SQLITE_CONFIG_MULTITHREAD/)運行時設置啟用

  1. 單線程

    編譯時SQLITE_THREADSAFE=0 默認啟用

    SQLITE_THREADSAFE=0/1/2

    sqlite3_config(SQLITE_CONFIG_SINGLETHREAD)
  1. 多線程

    編譯時SQLITE_THREADSAFE=2 默認啟用

    SQLITE_THREADSAFE=1/2

    sqlite3_config(SQLITE_CONFIG_MULTITHREAD)

  1. 串行

    編譯時SQLITE_THREADSAFE=1 默認啟用

    SQLITE_THREADSAFE=1/2

    sqlite3_config(SQLITE_CONFIG_SERIALIZED)

Ubuntu 18.04 的Sqlite3 默認發行版 為串行模式

數據庫文件鎖狀態

SQLite數據庫文件有5種鎖的狀態。一個線程只有在擁有低級別的鎖的時候,才能獲取更高一級的鎖。SQLite就是靠這5種類型的鎖,巧妙地實現了讀寫線程的互斥。同時也可看出,寫操作必須進入EXCLUSIVE狀態,此時並發數被降到1,這也是SQLite被認為並發插入性能不好的原因。另外,read-uncommitted和WAL模式會影響這個鎖的機制。在這2種模式下,讀線程不會被寫線程阻塞,即使寫線程持有PENDING或EXCLUSIVE鎖。

  1. UNLOCKED:表示數據庫此時並未被讀寫。
  2. SHARED:表示數據庫可以被讀取。SHARED鎖可以同時被多個線程擁有。一旦某個線程持有SHARED鎖,就沒有任何線程可以進行寫操作。
  3. RESERVED:表示准備寫入數據庫。RESERVED鎖最多只能被一個線程擁有,此后它可以進入PENDING狀態。
  4. PENDING:表示即將寫入數據庫,正在等待其他讀線程釋放SHARED鎖。一旦某個線程持有PENDING鎖,其他線程就不能獲取SHARED鎖。這樣一來,只要等所有讀線程完成,釋放SHARED鎖后,它就可以進入EXCLUSIVE狀態了。
  5. EXCLUSIVE:表示它可以寫入數據庫了。進入這個狀態后,其他任何線程都不能訪問數據庫文件。因此為了並發性,它的持有時間越短越好。

多線程並發訪問

在默認串行模式下,多線程並發訪問同一數據庫,每個線程開啟一個連接,同時訪問時會返回錯誤 "database is locked".此時需要等待數據庫可寫/可讀時才能訪問.

根據數據庫文件鎖狀態,這不典型的讀寫鎖嗎,哈哈哈,來個測試

測試代碼如下

全部代碼
讀寫鎖

// read thread
void read_thread() {
  Sqlite db;
  for (int i = 0; i < rw_count_; ++i) {
    if (use_lock_) {
      rwlock::LockRead _(lock_);
      db.test_read(i);
    } else {
      db.test_read(i);
    }
  }
}

// write thread
void write_thread() {
  Sqlite db;
  for (int i = 0; i < rw_count_; ++i) {
    if (use_lock_) {
      rwlock::LockWrite _(lock_);
      db.test_write(i);
    } else {
      db.test_write(i);
    }
  }
}

測試結果

測試: 2個讀線程,2個寫線程,每個線程訪問數據庫10次

環境: WSL Ubuntu 18.04

# 不開啟讀寫鎖
Read  Write   Times: 10
Read  Thread  Count: 2
Write Thread  Count: 2
Use Read Write Lock: 0
[139956121044800] db opened
[139956121044800] drop table user.
[139956121044800] create table user.
[139956121044800] insert data to user.
[139956121044800] db closed
[139956097255168] db opened
[139956005570304] db opened
[139956088801024] db opened
[139955997116160] db opened
[139956097255168] 0 db read OK.
[139956088801024] 0 db read OK.
[139956097255168] 1 db read OK.
[139956097255168] 2 db read error: database is locked
[139956088801024] 1 db read OK.
[139956097255168] 3 db read error: database is locked
[139956088801024] 2 db read error: database is locked
[139956097255168] 4 db read error: database is locked
[139956088801024] 3 db read error: database is locked
[139956097255168] 5 db read error: database is locked
[139956088801024] 4 db read error: database is locked
[139956097255168] 6 db read error: database is locked
[139956097255168] 7 db read error: database is locked
[139956088801024] 5 db read error: database is locked
[139956097255168] 8 db read error: database is locked
[139956088801024] 6 db read error: database is locked
[139956097255168] 9 db read error: database is locked
[139956088801024] 7 db read error: database is locked
[139956097255168] db closed
[139956088801024] 8 db read error: database is locked
[139956088801024] 9 db read error: database is locked
[139956088801024] db closed
[139955997116160] 0 db write error: database is locked
[139956005570304] 0 db write error: database is locked
[139956005570304] 1 db write error: database is locked
[139956005570304] 2 db write error: database is locked
[139956005570304] 3 db write error: database is locked
[139955997116160] 1 db write error: database is locked
[139955997116160] 2 db write error: database is locked
[139955997116160] 3 db write error: database is locked
[139956005570304] 4 db write error: database is locked
[139956005570304] 5 db write error: database is locked
[139956005570304] 6 db write error: database is locked
[139956005570304] 7 db write error: database is locked
[139956005570304] 8 db write error: database is locked
[139955997116160] 4 db write error: database is locked
[139955997116160] 5 db write error: database is locked
[139955997116160] 6 db write error: database is locked
[139955997116160] 7 db write error: database is locked
[139955997116160] 8 db write error: database is locked
[139955997116160] 9 db write error: database is locked
[139955997116160] db closed
[139956005570304] 9 db write OK.
[139956005570304] db closed
# 開啟讀寫鎖
Read  Write   Times: 10
Read  Thread  Count: 2
Write Thread  Count: 2
Use Read Write Lock: 1
[140635615070016] db opened
[140635615070016] drop table user.
[140635615070016] create table user.
[140635615070016] insert data to user.
[140635615070016] db closed
[140635591280384] db opened
[140635565917952] db opened
[140635582826240] db opened
[140635574372096] db opened
[140635591280384] 0 db read OK.
[140635582826240] 0 db read OK.
[140635591280384] 1 db read OK.
[140635582826240] 1 db read OK.
[140635591280384] 2 db read OK.
[140635582826240] 2 db read OK.
[140635591280384] 3 db read OK.
[140635582826240] 3 db read OK.
[140635591280384] 4 db read OK.
[140635582826240] 4 db read OK.
[140635591280384] 5 db read OK.
[140635582826240] 5 db read OK.
[140635591280384] 6 db read OK.
[140635582826240] 6 db read OK.
[140635591280384] 7 db read OK.
[140635582826240] 7 db read OK.
[140635591280384] 8 db read OK.
[140635582826240] 8 db read OK.
[140635591280384] 9 db read OK.
[140635582826240] 9 db read OK.
[140635591280384] db closed
[140635582826240] db closed
[140635565917952] 0 db write OK.
[140635565917952] 1 db write OK.
[140635565917952] 2 db write OK.
[140635565917952] 3 db write OK.
[140635565917952] 4 db write OK.
[140635565917952] 5 db write OK.
[140635565917952] 6 db write OK.
[140635565917952] 7 db write OK.
[140635565917952] 8 db write OK.
[140635565917952] 9 db write OK.
[140635565917952] db closed
[140635574372096] 0 db write OK.
[140635574372096] 1 db write OK.
[140635574372096] 2 db write OK.
[140635574372096] 3 db write OK.
[140635574372096] 4 db write OK.
[140635574372096] 5 db write OK.
[140635574372096] 6 db write OK.
[140635574372096] 7 db write OK.
[140635574372096] 8 db write OK.
[140635574372096] 9 db write OK.
[140635574372096] db closed

由上可見,不加鎖訪問數據庫返回錯誤 "database is locked"

加鎖訪問數據庫可以正常訪問了

讀寫鎖成功的起到了作用

OVER


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM