使用 FMDB for iOS 锁定数据库

Posted

技术标签:

【中文标题】使用 FMDB for iOS 锁定数据库【英文标题】:Database locked using FMDB for iOS 【发布时间】:2014-04-08 15:48:28 【问题描述】:

首先,我想说的是,我真的很难在后台线程中配置和使用我的 SQLite DB,以免主线程被阻塞。

在网上某处找到一个小指南后,我决定使用 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

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

如您所见,我有很多关于这个主题的知识,所以任何帮助都将不胜感激。

【问题讨论】:

嗨 Aleph72,你有没有找到解决这个问题的方法?我遇到了类似的问题,并且还认为数据库进程已序列化。现在我收到 DB 错误:5“数据库已锁定。” 【参考方案1】:

据我所知,您尚未创建此初始化调用的共享实例或单例实例

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

这应该是一个单例调用,因为您将创建多个 NSOperationQueue 实例,这将使数据库在多线程环境中易受攻击,尝试使用 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;

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

【讨论】:

以上是关于使用 FMDB for iOS 锁定数据库的主要内容,如果未能解决你的问题,请参考以下文章

iOS之sqlite和FMDB

如何在 swift 3 中使用现有的 SQLite? (FMDB)

iOS开发之--FMDB的使用

iOS 数据库第三方FMDB的简单使用

IOS数据库FMDB增删改查的使用原创

iOS开发--SQLite重要框架FMDB的使用