锁定数据库查询 FMDB?
Locks on DB queries FMDB?
我在我的应用程序中使用多线程环境,我需要不断访问 sqlite 数据库以更新我的视图,并通过多个后台线程使用服务器数据更新我的数据库。现在我正在使用 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];
}
}
}];
这就是我每次插入数据时所做的,以及当我在锁定时从数据库中读取数据时以类似的方式进行的操作,在一个线程完成之前,进程不应该能够访问数据库。我不知道出了什么问题,请帮帮我。
每当多个线程尝试访问相同的 table 进行读写或两个线程想要在相同的 table 上写入相同的数据库时,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 以获得更好的理解,希望这对您有所帮助,我是堆栈的新手所以请多多包涵谢谢。
使用FMDatabaseQueue
完全不需要任何其他锁定机制。添加另一个锁定机制只会使问题进一步复杂化。
如果您收到关于数据库 "locked" 的消息,那是因为:
你有多个 FMDatabase
/FMDatabaseQueue
对象;或
您正在从另一个 inDatabase
呼叫中呼叫 inDatabase
。
你应该有一个 FMDatabaseQueue
对象,它在所有线程之间共享,你需要确保 none 用 inDatabase
块调用的函数调用其他东西它本身会尝试另一个 inDatabase
调用。
我在我的应用程序中使用多线程环境,我需要不断访问 sqlite 数据库以更新我的视图,并通过多个后台线程使用服务器数据更新我的数据库。现在我正在使用 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];
}
}
}];
这就是我每次插入数据时所做的,以及当我在锁定时从数据库中读取数据时以类似的方式进行的操作,在一个线程完成之前,进程不应该能够访问数据库。我不知道出了什么问题,请帮帮我。
每当多个线程尝试访问相同的 table 进行读写或两个线程想要在相同的 table 上写入相同的数据库时,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 以获得更好的理解,希望这对您有所帮助,我是堆栈的新手所以请多多包涵谢谢。
使用FMDatabaseQueue
完全不需要任何其他锁定机制。添加另一个锁定机制只会使问题进一步复杂化。
如果您收到关于数据库 "locked" 的消息,那是因为:
你有多个
FMDatabase
/FMDatabaseQueue
对象;或您正在从另一个
inDatabase
呼叫中呼叫inDatabase
。
你应该有一个 FMDatabaseQueue
对象,它在所有线程之间共享,你需要确保 none 用 inDatabase
块调用的函数调用其他东西它本身会尝试另一个 inDatabase
调用。