我在我的应用程序中使用多线程环境,我需要不断访问 sqlite 数据库以更新我的 View ,并通过多个后台线程使用服务器数据更新我的数据库。现在我正在使用 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];
}
}
}];
这就是我每次插入数据时所做的事情,以及当我在锁定时从数据库读取数据时类似的方式,在一个线程完成之前,进程不应该能够访问数据库。我不知道出了什么问题请帮帮我。
最佳答案
每当多个线程尝试访问同一个表进行读写或两个线程想要在同一数据库 SQLite 的同一个表上写入时,都会产生数据库锁定信号,因此要解决此问题,您需要锁
NSRecursiveLock *_writeQueueLock = [NSRecursiveLock new];
正如您在代码中添加的那样,但这对您没有多大帮助,因为您每次插入时都试图创建一个新锁。 这个锁应该是一个单一的对象,用于所有对数据库的阻塞调用,如插入、更新、删除等。
尝试创建锁的单例实例,这应该有帮助:
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;
}
现在,一旦创建了对象,您就可以在这些队列和锁上调用插入、更新、删除方法,例如:
[_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为了更好地理解,希望这会有所帮助,我是该堆栈的新手,所以请多一点宽容,谢谢。
关于ios - DB 查询上的锁 FMDB?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29515323/