FMDB的線程安全

最近面試被問到FMDB的多線程處理問題,由於以前項目中是移植別人的代碼,沒有踩過這裏的坑。html

問題:

多線程同時訪問數據庫時,報數據庫鎖定的問題,錯誤信息是:面試

Unknown error finalizing or resetting statement (5: database is locked)sql

緣由:

文件數據庫sqlite,同一時刻容許多個進程/線程讀,但同一時刻只容許一個線程寫。在操行寫操做時,數據庫文件被瑣定,此時任何其餘讀/寫操做都被阻塞,若是阻塞超過5秒鐘(默認是5秒,能太重新編譯sqlite能夠修改超時時間),就報"database is locked"錯誤。因此,在操做sqlite時,應該即時關閉鏈接;打開鏈接後,儘可能減小很是費時的操做。數據庫

 

解決:

FMDatabase **不能多線程使用一個實例多線程訪問數據庫,不能使用同一個**FMDatabase 的實例。不然會發生異常。若是線程使用單獨的FMDatabase 實例是容許的,可是一樣有可能發生database is locked的問題。這是因爲多線程對sqlite的競爭引發的.多線程

 

FMDatabaseQueue 解決這個問題的思路是:建立一個隊列(串行線程隊列),而後將放入的隊列的block順序執行,這樣避免了多線程同時訪問數據庫線程

解決方案 共享同一個FMDatabaseQueue**實例**orm

 

注意:sqlite

本來使用FMDatabase類,須要手工調用db的open和close方法,可是用FMDatabaseQueue,不須要調用open,由於查看代碼發現,Queue已經open了。htm

因此,使用Queue,是不須要本身打開和關閉db的。可是若是使用了FMResultSet,rs卻是須要關閉,不然會報warning:
if ([db hasOpenResultSets]) {
NSLog(@"Warning: there is at least one open result set around after performing [FMDatabaseQueue inDatabase:]");
隊列

 

引伸閱讀

加入GCD信號量控制

Reference:

IOS 使用FMDB多線程訪問數據庫 及databaseislocked的問題

相關文章
相關標籤/搜索