Sqlite3併發讀寫注意事項

sqlite3的鎖及事務類型
sqlite3總共有三種事務類型:BEGIN [DEFERRED /IMMEDIATE / EXCLUSIVE] TRANSCATION,
五種鎖,按鎖的級別依次是:UNLOCKED /SHARED /RESERVERD /PENDING /EXCLUSIVE。

當執行select即讀操作時,需要獲取到SHARED鎖(共享鎖),
當執行insert/update/delete操作(即內存寫操作時),
需要進一步獲取到RESERVERD鎖(保留鎖),
當進行commit操作(即磁盤寫操作時),需要進一步獲取到EXCLUSIVE鎖(排它鎖)。

對於RESERVERD鎖,sqlite3保證同一時間只有一個連接可以獲取到保留鎖,也就是同一時間只有一個連接可以寫數據庫(內存),但是其它連接仍然可以獲取SHARED鎖,也就是其它連接仍然可以進行讀操作(這裏可以認爲寫操作只是對磁盤數據的一份內存拷貝進行修改,並不影響讀操作)。

對於EXCLUSIVE鎖,是比保留鎖更爲嚴格的一種鎖,在需要把修改寫入磁盤即commit時需要在保留鎖/未決鎖的基礎上進一步獲取到排他鎖,顧名思義,排他鎖排斥任何其它類型的鎖,即使是SHARED鎖也不行,所以,在一個連接進行commit時,其它連接是不能做任何操作的(包括讀)。

PENDING鎖(即未決鎖),則是比較特殊的一種鎖,它可以允許已獲取到SHARED鎖的事務繼續進行,但不允許其它連接再獲取SHARED鎖,當已存在的SHARED鎖都被釋放後(事務執行完成),持有未決鎖的事務就可以獲得commit的機會了。sqlite3使用這種鎖來防止writer starvation(寫餓死)。

這裏寫圖片描述

死鎖的情況
死鎖的情況:當兩個連接使用begin transaction開始事務時,
第一個連接執行了一次select操作(已經獲取到SHARED鎖),
第二個連接執行了一次insert操作(已經獲取到了RESERVERD鎖),
此時第一個連接需要進行一次insert/update/delete(需要獲取到RESERVERD鎖),
第二個連接則希望執行commit(需要獲取到EXCLUSIVE鎖),由於第二個連接已經獲取到了RESERVERD鎖,根據RESERVERD鎖同一時間只有一個連接可以獲取的特性,第一個連接獲取RESERVERD鎖的操作必定失敗,
而由於第一個連接已經獲取到SHARED鎖,第二個連接希望進一步獲取到EXCLUSIVE鎖的操作也必定失敗。就導致了事務死鎖。

事務類型的使用原則
在用”begin transaction”顯式開啓一個事務時,默認的事務類型爲DEFERRED,鎖的狀態爲UNLOCKED,即不獲取任何鎖,如果在使用的數據庫沒有其它的連接,用begin就可以了。如果有多個連接都需要對數據庫進行寫操作,那就得使用BEGIN IMMEDIATE/EXCLUSIVE開始事務了。
使用事務的好處是:
1.一個事務的所有操作相當於一次原子操作,如果其中某一步失敗,可以通過回滾來撤銷之前所有的操作,只有當所有操作都成功時,才進行commit,保證了操作的原子特性;
2.對於多次的數據庫操作,如果我們希望提高數據查詢或更新的速度,可以在開始操作前顯式開啓一個事務,在執行完所有操作後,再通過一次commit來提交所有的修改或結束事務。

對SQLITE_BUSY的處理
當有多個連接同時對數據庫進行寫操作時,根據事務類型的使用原則,我們在每個連接中用BEGIN IMMEDIATE開始事務,即多個連接都嘗試取得保留鎖的情況,根據保留鎖同一時間只有一個連接可以獲取到的特性,其它連接都將獲取失敗,即事務開始失敗,這種情況下,sqlite3將返回一個SQLITE_BUSY的錯誤,如果我們不希望操作就此失敗而返回,就必須處理SQLITE_BUSY的情況,
sqlite3提供了sqlite3_busy_handler或sqlite3_busy_timeout來處理SQLITE_BUSY,
對於sqlite3_busy_handler,我們可以指定一個busy_handler來處理,並可以指定失敗重試的次數。
而sqlite3_busy_timeout則是由sqlite3自動進行sleep並重試,當sleep的累積時間超過指定的超時時間時,最終返回SQLITE_BUSY。
需要注意的是,這兩個函數同時只能使用一個,後面的調用會覆蓋掉前次調用。從使用上來說,sqlite3_busy_timeout更易用一些,只需要指定一個總的超時時間,然後sqlite自己會決定多久進行重試以及重試的次數,直到達到總的超時時間最終返回SQLITE_BUSY。並且,這兩個函數一經調用,對其後的所有數據庫操作都有效,非常方便。

參考:
http://www.sqlite.org/lockingv3.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章