锁定数据库查询FMDB?

时间:2015-04-08 12:58:14

标签: ios database fmdb locked

我在我的应用程序中使用多线程环境,我需要不断访问sqlite db以更新我的视图,并通过多个后台线程更新我的数据库与服务器数据。现在我使用FMDB进行数据库交互,但仍然遇到数据库锁定问题。

FMDatabaseQueue *_queue = [FMDatabaseQueue databaseQueueWithPath:databasePath];
NSOperationQueue *_writeQueue = [NSOperationQueue new];
[_writeQueue setMaxConcurrentOperationCount:1];
NSRecursiveLock *_writeQueueLock = [NSRecursiveLock new];
[_writeQueue addOperationWithBlock:^{
            BOOL tryLock = NO;
            @try {
                [_writeQueueLock lock];
                tryLock = YES;
                [_queue inDatabase:^(FMDatabase *db) {
                    @try {
                        [db logsErrors];
                        [db executeUpdate:updateSQL];
                    }
                    @catch (NSException *exception) {

                    }
                    @finally {

                    }
                }];
            }
            @catch (NSException *exception) {

                NSLog(@"Error while inserting data saveLocation inside operation queue. %@", exception.description);
            }
            @finally {
                if (tryLock) {
                    [_writeQueueLock unlock];
                }
            }
}];

这是我每次插入数据时所做的事情以及当我从DB读取数据时的类似方式,在一个线程完成之前,进程应该无法访问数据库。我不知道有什么不对,请帮帮我。

2 个答案:

答案 0 :(得分:2)

每当多个线程尝试访问同一个表进行读写操作或两个线程想要写入同一个数据库的同一个数据库时,sqlite会生成数据库锁定信号,所以要解决此问题需要锁定

NSRecursiveLock *_writeQueueLock = [NSRecursiveLock new];

正如您在代码中添加的那样,但这对您来说并没有多大帮助,因为每次插入时都会尝试使用新锁。 对于所有对DB的阻塞调用,此锁应该是单个对象,如插入,更新,删除等。

尝试创建一个单独的锁实例,这应该有帮助:

static FMDatabaseQueue *_queue;
static NSOperationQueue *_writeQueue;
static NSRecursiveLock *_writeQueueLock;

+(SomeDBClass*)getSharedInstance{
    if (!sharedInstance) {
        sharedInstance = [[super allocWithZone:NULL]init];
        _queue = [FMDatabaseQueue databaseQueueWithPath:databasePath];
        _writeQueue = [NSOperationQueue new];
       [_writeQueue setMaxConcurrentOperationCount:1];
        _writeQueueLock = [NSRecursiveLock new];
    }
    return sharedInstance;
}

现在,一旦创建了对象,就可以在这些队列上调用insert,update,delete方法,并锁定:

[_writeQueue addOperationWithBlock:^{
            BOOL tryLock = NO;
            @try {
                [_writeQueueLock lock];
                tryLock = YES;
                [_queue inDatabase:^(FMDatabase *db) {
                    @try {
                        [db logsErrors];
                        [db executeUpdate:updateSQL];
                    }
                    @catch (NSException *exception) {

                    }
                    @finally {

                    }
                }];
            }
            @catch (NSException *exception) {

                NSLog(@"Error while inserting data saveLocation inside operation queue. %@", exception.description);
            }
            @finally {
                if (tryLock) {
                    [_writeQueueLock unlock];
                }
            }
}];

你也可以参考this以获得更好的理解,希望这有帮助,我是新手,所以请稍微宽容谢谢。

答案 1 :(得分:1)

使用FMDatabaseQueue完全消除了对任何其他锁定机制的需要。添加另一种锁定机制只会使问题进一步复杂化。

如果您收到有关数据库被锁定"的消息,则因为:

  • 你有多个FMDatabase / FMDatabaseQueue个对象;或

  • 您在另一个inDatabase来电中呼叫inDatabase

你应该有一个FMDatabaseQueue对象在所有线程之间共享,你需要确保用inDatabase块调用的所有函数都不会调用其他自己尝试另一个inDatabase的函数{{1}} 1}}来电。