使用FMDB for iOS锁定数据库

时间:2014-04-08 15:48:29

标签: ios multithreading sqlite fmdb

首先,我想说我在后台线程中尝试配置和使用我的SQLite数据库时遇到了不好的时间,因此主线程没有被阻止。

在互联网上找到一个小指南之后,我决定选择FMDB包装。

与数据库操作相关的所有方法都在同一个类中,这就是我遇到错误的地方:

我已经设置了这样的静态变量:

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

然后在我的init方法中我有:

- (id)init {
    self = [super init];
    if (self) {
        _queue = [FMDatabaseQueue databaseQueueWithPath:[self GetDocumentPath]];
        _writeQueue = [NSOperationQueue new];
        [_writeQueue setMaxConcurrentOperationCount:1];
        _writeQueueLock = [NSRecursiveLock new];
    }
    return self;
}

这是给我错误的方法:

- (void)UpdateTime:(NSString *)idT :(int)userId {
    [_writeQueue addOperationWithBlock:^{
    [_writeQueueLock lock];
    [_queue inDatabase:^(FMDatabase *dbase) {
        AppDelegate *deleg = (AppDelegate *)[[UIApplication sharedApplication] delegate];
        if (![dbase executeUpdate:@"update orari set orario=datetime(orario, '? minutes') where nome=? and dataid>=? and idutente=?"
             withArgumentsInArray:@[[NSNumber numberWithFloat:deleg.diff], deleg.nome, [NSNumber numberWithInt:deleg.idMed], [NSNumber numberWithInt: userId]]]) {
            NSLog(@"error");
        }
    }];
        [_writeQueueLock unlock];
    }];

    [_writeQueue addOperationWithBlock:^{
        [_writeQueueLock lock];
        [_queue inDatabase:^(FMDatabase *dbase) {
            AppDelegate *deleg = (AppDelegate *)[[UIApplication sharedApplication] delegate];
            if (![dbase executeUpdate:@"UPDATE orari SET presa=1 where dataid=? and idutente=?"
                 withArgumentsInArray:@[[NSNumber numberWithInt:deleg.identific], [NSNumber numberWithInt: userId]]]) {
                NSLog(@"error");
        }
        }];
        [_writeQueueLock unlock];
    }];
    [self AddNotification];
}

这些是我得到的错误:

*** -[NSRecursiveLock dealloc]: lock (<NSRecursiveLock: 0xc38b350> '(null)') deallocated while still in use
DB Error: 5 "database is locked"
*** -[NSRecursiveLock unlock]: lock (<NSRecursiveLock: 0x13378d20> '(null)') unlocked when not locked

从我读过的指南中,我认为对我的数据库的访问将被“序列化”,并且每次更新都会被添加到队列中并一次执行一次。

正如您所看到的,我有很多东西可以学习这个主题,所以任何帮助都会非常感激。

1 个答案:

答案 0 :(得分:0)

我可以看到你没有创建这个init调用的共享实例或单例实例

- (id)init {
    self = [super init];
    if (self) {
        _queue = [FMDatabaseQueue databaseQueueWithPath:[self GetDocumentPath]];
        _writeQueue = [NSOperationQueue new];
        [_writeQueue setMaxConcurrentOperationCount:1];
        _writeQueueLock = [NSRecursiveLock new];
    }
    return self;
}

这应该是一个单独调用,因为您将创建多个NSOperationQueue实例,这将使DB在多线程环境中易受攻击,尝试使用GCD或

对数据库进行单例调用
static DBManager *sharedInstance = nil;
+(DBManager*)getSharedInstance{

    if (!sharedInstance) {
        sharedInstance = [[super allocWithZone:NULL]init];
        _queue = [FMDatabaseQueue databaseQueueWithPath:[self GetDocumentPath]];
            _writeQueue = [NSOperationQueue new];
            [_writeQueue setMaxConcurrentOperationCount:1];
            _writeQueueLock = [NSRecursiveLock new];
    }
    return sharedInstance;
}

它可能会解决您的问题,这是我第一次在这里回答,我是新手,所以请稍微宽容一点:)谢谢