FMDB與線程安全

簡介

FMDB是對蘋果SQLite的封裝

多線程操作

1. 如果出現(xiàn)多個(gè)線程同時(shí)操作數(shù)據(jù)庫,怎么辦,用他,用他,F(xiàn)MDatabaseQueue
FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:path];

[queue inDatabase:^(FMDatabase *db) {
        
        [db executeUpdate:@"INSERT INTO myTable (name) VALUES (?)", @"will"];
        [db executeUpdate:@"INSERT INTO myTable (name) VALUES (?)", @"carter"];
        
        FMResultSet *rs = [db executeQuery:@"select name from myTable"];
        while([rs next]) {
            NSString *obj = [rs stringForColumn:@"name"];
            NSLog(@"%@", obj);
        }
        
    }];
2. 大量查詢數(shù)據(jù)庫的情況

比如循環(huán)1000次執(zhí)行插入查詢的操作

FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:self.filePath];
    for (NSInteger i = 0; i < 1000; i ++) {
        [queue inDatabase:^(FMDatabase *db) {
            
            [db executeUpdate:@"INSERT INTO myTable (name) VALUES (?)", @"will"];
            [db executeUpdate:@"INSERT INTO myTable (name) VALUES (?)", @"carter"];
            
            FMResultSet *rs = [db executeQuery:@"select name from myTable"];
            while([rs next]) {
                NSString *obj = [rs stringForColumn:@"name"];
                NSLog(@"%@", obj);
            }
            
        }];
    }
image.png

結(jié)果發(fā)現(xiàn)按鈕一直處于被點(diǎn)擊狀態(tài),說明已經(jīng)阻塞了主線程,看了inDatabase的源碼

FMDatabaseQueue *currentSyncQueue = (__bridge id)dispatch_get_specific(kDispatchQueueSpecificKey);
    assert(currentSyncQueue != self && "inDatabase: was called reentrantly on the same queue, which would lead to a deadlock");
    
    FMDBRetain(self);
    
    dispatch_sync(_queue, ^() {
        
        FMDatabase *db = [self database];
        block(db);
        
        if ([db hasOpenResultSets]) {
            NSLog(@"Warning: there is at least one open result set around after performing [FMDatabaseQueue inDatabase:]");
            
#if defined(DEBUG) && DEBUG
            NSSet *openSetCopy = FMDBReturnAutoreleased([[db valueForKey:@"_openResultSets"] copy]);
            for (NSValue *rsInWrappedInATastyValueMeal in openSetCopy) {
                FMResultSet *rs = (FMResultSet *)[rsInWrappedInATastyValueMeal pointerValue];
                NSLog(@"query: '%@'", [rs query]);
            }
#endif
        }
    });
    
    FMDBRelease(self);

發(fā)現(xiàn)他是用同步的方法進(jìn)行的操作,這樣就避免了多線程鎖死的情況,但是確定呢就是會(huì)阻塞主線程,所以,有如下解決方法:

  • 在inDatabase的外面套了個(gè)異步,就不會(huì)阻塞主線程了
FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:self.filePath];
    for (NSInteger i = 0; i < 1000; i ++) {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            [queue inDatabase:^(FMDatabase *db) {
                
                [db executeUpdate:@"INSERT INTO myTable (name) VALUES (?)", @"will"];
                [db executeUpdate:@"INSERT INTO myTable (name) VALUES (?)", @"carter"];
                
                FMResultSet *rs = [db executeQuery:@"select name from myTable"];
                while([rs next]) {
                    NSString *obj = [rs stringForColumn:@"name"];
                    NSLog(@"%@", obj);
                }
                
            }];
        });
    }
image.png
image.png

哈哈,就是線程有點(diǎn)多

  • 用inTransaction事務(wù)方法查詢,會(huì)比inDatabase速度快些
FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:self.filePath];
    [queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
        for (NSInteger i = 0; i < 1000; i ++) {
            BOOL isSuccess = [db executeUpdate:@"INSERT INTO myTable (name) VALUES (?)", @"will"];
            
            if (!isSuccess) {
                *rollback = YES;
                break;
            }else{
                NSLog(@"success");
            }
            
        }
    }];
  • 或者拆解查詢的數(shù)量,慢慢來
3. 前面的FMDatabaseQueue都是用同步的方法來實(shí)現(xiàn),我們自定義一個(gè)FMDatabaseAsynQueue,用異步加線程鎖的方法嘗試看看
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • iOS中原生的SQLite API在使用上相當(dāng)不友好,在使用時(shí),非常不便。于是,就出現(xiàn)了一系列將SQLite AP...
    Icec閱讀 1,394評論 1 13
  • FMDB v2.6.2 這是個(gè)SQLite的OC封裝。SQLite的地址:http://sqlite.org/ F...
    原鳴清閱讀 2,413評論 0 3
  • 優(yōu)秀的第三方庫,README 也是很優(yōu)秀的,理解了 README,會(huì)對使用帶來很多便利。 ARC 和 MRC 項(xiàng)目...
    月上樓閣閱讀 677評論 0 0
  • 閱讀完本書,首先給我的感覺是內(nèi)容有點(diǎn)對不起它的¥59.80定價(jià),全書主要講了兩塊內(nèi)容,一塊是SQLite3,...
    瑞小萌閱讀 3,127評論 4 33
  • The only limit is your imagination. 唯一的局限是你的想象力。 我是新手,一個(gè)...
    小小猿閱讀 911評論 2 4

友情鏈接更多精彩內(nèi)容