FMDB database locked問題解析

FMDB可能是iOS中最常用的數據庫第三方框架. 在項目中, 對于簡單的數據, 我們一般是儲存在偏好設置中, 或者存入XML文件, 需要的時候再讀取. 但是對于大量的數據, 或者是需要后續(xù)頻繁操作的數據, 我們只能把這些數據存入數據庫中.

在最近的一個項目中, 就遇到了需要頻繁操作數據庫內數據的情況, 頻繁的增刪讀寫.隨之而來的就遇到了數據庫鎖死問題. FMDB報錯為database locked.

首先先弄懂為什么會出現數據庫鎖死問題. 當A在寫入數據的時候, 會先鎖定數據庫再進行寫入操作. 然而這時, B又馬上想寫入數據, 因為數據庫已經被A鎖住了, 所以B無法進行寫入操作, 只能先等待A操作完成后再打開數據庫. 當等待的時間過長的時候, 數據庫就會報database locked錯誤. 這個時間好像是2s.

這里先貼出源碼中的一句話 :

Using a single instance of <FMDatabase> from multiple threads at once is a bad idea. It has always been OK to make a <FMDatabase> object per thread. Just don't share a single instance across threads, and definitely not across multiple threads at the same time.

告訴我們別妄想著把database做成單例, 也別想著使用多線程訪問database對象. 那我們應該怎么處理數據庫鎖死問題呢? 官方已經給出了答案:

Instead, use FMDatabaseQueue.

然后, 樓主參考了網絡各路大神的意見, 一致的解決版本是建立一個DatabaseHelper的類, 用來管理數據庫, 應該說是管理數據庫線程. 即是把FMDatabaseQueue做成一個單例, 所有的的數據庫操作在這個線程中串行執(zhí)行. 當需要執(zhí)行一個操作時, 先把操作放入串行隊列, 執(zhí)行完前一個操作再執(zhí)行下一個操作.

上代碼:

#import "BPBDBHelper.h"

@implementation BPBDBHelper

{
    FMDatabaseQueue* queue;
}

- (id)init {
    self = [super init];
    if(self){
        NSString *dbFilePath = [self getDatabasePath];
        queue = [FMDatabaseQueue databaseQueueWithPath:dbFilePath];
    }
    return self;
}

+ (BPBDBHelper *)sharedInstance {
    static dispatch_once_t pred = 0;
    __strong static id _sharedObject = nil;
    dispatch_once(&pred, ^{
        _sharedObject = [[self alloc] init];
    });
    return _sharedObject;
}

- (void)inDatabase:(void(^)(FMDatabase*))block {
    [queue inDatabase:^(FMDatabase *db){
        if ([db open]) {
            block(db);
        }
        [db close];
    }];
}

- (BOOL)creatDatabase {
    [queue inDatabase:^(FMDatabase *db) {
        //創(chuàng)建表
        if ([db open]) {
            NSString *positionSql = @"CREATE TABLE IF NOT EXISTS 'position' (******)";
            [db executeUpdate:positionSql];
       }
        [db close];
    }];
    return true;
}

- (NSString *)getDatabasePath {
    NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    NSString *filePath = [documentsPath stringByAppendingPathComponent:@"position.sqlite"];
    return filePath;
}

+ (void)refreshDatabaseFile {
    BPBDBHelper *instance = [self sharedInstance];
    [instance doRefresh];
}

- (void)doRefresh {
    NSString *dbFilePath = [self getDatabasePath];
    queue = [FMDatabaseQueue databaseQueueWithPath:dbFilePath];
}
@end

之后, 只需要把對數據庫的各種操作都放入- (void)inDatabase:(void(^)(FMDatabase*))block內執(zhí)行就行了.


由于筆者知識有限,如有錯誤蚣抗,歡迎討論指出卓起。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末烙常,一起剝皮案震驚了整個濱河市蛾魄,隨后出現的幾起案子征峦,更是在濱河造成了極大的恐慌情屹,老刑警劉巖柏锄,帶你破解...
    沈念sama閱讀 221,406評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件酿箭,死亡現場離奇詭異,居然都是意外死亡趾娃,警方通過查閱死者的電腦和手機缭嫡,發(fā)現死者居然都...
    沈念sama閱讀 94,395評論 3 398
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來抬闷,“玉大人妇蛀,你說我怎么就攤上這事耕突。” “怎么了评架?”我有些...
    開封第一講書人閱讀 167,815評論 0 360
  • 文/不壞的土叔 我叫張陵眷茁,是天一觀的道長。 經常有香客問我纵诞,道長上祈,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,537評論 1 296
  • 正文 為了忘掉前任浙芙,我火速辦了婚禮登刺,結果婚禮上,老公的妹妹穿的比我還像新娘嗡呼。我一直安慰自己纸俭,他們只是感情好,可當我...
    茶點故事閱讀 68,536評論 6 397
  • 文/花漫 我一把揭開白布南窗。 她就那樣靜靜地躺著揍很,像睡著了一般。 火紅的嫁衣襯著肌膚如雪矾瘾。 梳的紋絲不亂的頭發(fā)上女轿,一...
    開封第一講書人閱讀 52,184評論 1 308
  • 那天箭启,我揣著相機與錄音壕翩,去河邊找鬼。 笑死傅寡,一個胖子當著我的面吹牛放妈,可吹牛的內容都是我干的。 我是一名探鬼主播荐操,決...
    沈念sama閱讀 40,776評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼芜抒,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了托启?” 一聲冷哼從身側響起宅倒,我...
    開封第一講書人閱讀 39,668評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎屯耸,沒想到半個月后拐迁,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 46,212評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡疗绣,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,299評論 3 340
  • 正文 我和宋清朗相戀三年线召,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片多矮。...
    茶點故事閱讀 40,438評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡缓淹,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情讯壶,我是刑警寧澤料仗,帶...
    沈念sama閱讀 36,128評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站伏蚊,受9級特大地震影響罢维,放射性物質發(fā)生泄漏。R本人自食惡果不足惜丙挽,卻給世界環(huán)境...
    茶點故事閱讀 41,807評論 3 333
  • 文/蒙蒙 一肺孵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧颜阐,春花似錦平窘、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,279評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至肤舞,卻和暖如春紫新,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背李剖。 一陣腳步聲響...
    開封第一講書人閱讀 33,395評論 1 272
  • 我被黑心中介騙來泰國打工芒率, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人篙顺。 一個月前我還...
    沈念sama閱讀 48,827評論 3 376
  • 正文 我出身青樓偶芍,卻偏偏與公主長得像,于是被迫代替她去往敵國和親德玫。 傳聞我的和親對象是個殘疾皇子匪蟀,可洞房花燭夜當晚...
    茶點故事閱讀 45,446評論 2 359

推薦閱讀更多精彩內容