2012年10月25日 星期四

SQLite Concurrency

SQLite 本身自稱在 concurrency 方面只有有限度的支援
有關 SQLite 如何處理 Lock 和 Concurrency,可以參考 SQLite 官方文件 [1]。
大體上可以理解為 SQLite 的上鎖機制很像是 Java 的 ReadWriteLock
亦即對同一個 SQLite 資料庫而言,允許多個程序同時讀取,但最多只允許一個程序進行寫入
寫入期間就是使用一般的 exclusive lock 將整個資料庫鎖住。
這大概也就是為什麼 SQLite 官方說他們只支援 1 transaction 吧。

SQLite version 3 目前對於一個資料庫的檔案,總共有 5 種狀態:UNLOCKED、SHARED、RESERVED、PENDING 和 EXCLUSIVE。
  • UNLOCKED:一般未上鎖的狀態。即沒有任何程序正在讀寫資料庫檔案。
  • SHARED:讀取的狀態。一個資料庫檔案可以同時被很多個程序取得 SHARED-Lock,亦即資料庫檔案允許同時很多個程序一起讀取資料庫檔案的內容。
  • RESERVED:預備寫入的狀態。一個資料庫檔案同時只能有一個程序取得 RESERVED-Lock,當有程序取得 RESERVED-Lock 時,表示該程序已經正在準備,預計之後要寫入資料。在 RESERVED-Lock 被取得後,其他程序仍然可以取得 SHARED-Lock,但若是想要取得 RESERVED-Lock 的話會被回絕。
  • PENDING:RESERVED-Lock 的下一步,要寫入的程序已經要寫入了。要求 PENDING-Lock 的程序此時會等待所有 SHARED-Lock 被釋放(即所有正在讀取資料庫的程序都讀取結束),這時資料庫檔案不允許新的程序取得 SHARED-Lock,只能等待所有已經被取得的 SHARED-Lock 全部被釋放。
  • EXCLUSIVE:PENDING 狀態的下一步,某一程序正在寫入的狀態。這就是一般的 exclusive lock 的狀態,資料庫檔案只允許單一程序(即目前正在寫入的程序)進行資料庫的讀寫。

不過根據 [2] 的回應,jowo 提到了以下的內容:
Shared-cache mode does not affect the number of transactions. When shared cache is turned off, each database connection must lock the database file exclusively to write to it. So only one write transaction is available to all connections. However, in shared-cache mode locking is done on a per-table basis for all threads within the process.In either mode, reads can be done in parallel.
亦即在一般預設狀況下(Shared-cache mode 關閉的狀況),同時只能有一個 transaction 被 commit
這跟上面講的並不衝突,因為同時只能有一個程序要求 EXCLUSIVE-Lock。
不過在 Shared-cache mode 開啟時,狀況可能就不太一樣了~。

根據官方文件 [3] 的描述,在 SQLite 3.3.0 以上版本開始支援 Shared-cache mode。


使用 Shared-cache 的範例圖。(圖片轉錄自 [3])

以下節錄在 [3] 中對於上圖的描述。
Connection 1 is a normal SQLite database connection. Connections 2 and 3 share a cache The normal locking protocol is used to serialize database access between connection 1 and the shared cache.

就我看了 [3] 之後的了解,當有多個程序或者執行緒共用同一個 Shared-cache 時
單獨對這個 Shared-cache 的連線來說,可以以資料表為單位做 write-lock。
但是對實際存取資料庫檔案的每個連線(即圖中的 Shared-cache 和 Connection 1)來說,原始的上鎖機制仍然存在
也就是說,雖然 Shared-cache 可以允許多個程序或執行緒寫入不同的資料表
但 Shared-cache 要真正把修改的資料寫入磁碟時,仍然要跟其他連線競爭 EXCLUSIVE-Lock。

參考資料:
1、File Locking And Concurrency In SQLite Version 3
2、sqlite only supports 1 transaction?
3、SQLite Shared-Cache Mode

沒有留言: