简介
FMDB是对苹果SQLite的封装
多线程操作
1. 如果出现多个线程同时操作数据库,怎么办,用他,用他,FMDatabaseQueue
FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:path];
[queue inDatabase:^(FMDatabase *db) {
[db executeUpdate:@"INSERT INTO myTable (name) VALUES (?)", @"will"];
[db executeUpdate:@"INSERT INTO myTable (name) VALUES (?)", @"carter"];
FMResultSet *rs = [db executeQuery:@"select name from myTable"];
while([rs next]) {
NSString *obj = [rs stringForColumn:@"name"];
NSLog(@"%@", obj);
}
}];
2. 大量查询数据库的情况
比如循环1000次执行插入查询的操作
FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:self.filePath];
for (NSInteger i = 0; i < 1000; i ++) {
[queue inDatabase:^(FMDatabase *db) {
[db executeUpdate:@"INSERT INTO myTable (name) VALUES (?)", @"will"];
[db executeUpdate:@"INSERT INTO myTable (name) VALUES (?)", @"carter"];
FMResultSet *rs = [db executeQuery:@"select name from myTable"];
while([rs next]) {
NSString *obj = [rs stringForColumn:@"name"];
NSLog(@"%@", obj);
}
}];
}
结果发现按钮一直处于被点击状态,说明已经阻塞了主线程,看了inDatabase的源码
FMDatabaseQueue *currentSyncQueue = (__bridge id)dispatch_get_specific(kDispatchQueueSpecificKey);
assert(currentSyncQueue != self && "inDatabase: was called reentrantly on the same queue, which would lead to a deadlock");
FMDBRetain(self);
dispatch_sync(_queue, ^() {
FMDatabase *db = [self database];
block(db);
if ([db hasOpenResultSets]) {
NSLog(@"Warning: there is at least one open result set around after performing [FMDatabaseQueue inDatabase:]");
#if defined(DEBUG) && DEBUG
NSSet *openSetCopy = FMDBReturnAutoreleased([[db valueForKey:@"_openResultSets"] copy]);
for (NSValue *rsInWrappedInATastyValueMeal in openSetCopy) {
FMResultSet *rs = (FMResultSet *)[rsInWrappedInATastyValueMeal pointerValue];
NSLog(@"query: '%@'", [rs query]);
}
#endif
}
});
FMDBRelease(self);
发现他是用同步的方法进行的操作,这样就避免了多线程锁死的情况,但是确定呢就是会阻塞主线程,所以,有如下解决方法:
- 在inDatabase的外面套了个异步,就不会阻塞主线程了
FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:self.filePath];
for (NSInteger i = 0; i < 1000; i ++) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[queue inDatabase:^(FMDatabase *db) {
[db executeUpdate:@"INSERT INTO myTable (name) VALUES (?)", @"will"];
[db executeUpdate:@"INSERT INTO myTable (name) VALUES (?)", @"carter"];
FMResultSet *rs = [db executeQuery:@"select name from myTable"];
while([rs next]) {
NSString *obj = [rs stringForColumn:@"name"];
NSLog(@"%@", obj);
}
}];
});
}
哈哈,就是线程有点多
- 用inTransaction事务方法查询,会比inDatabase速度快些
FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:self.filePath];
[queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
for (NSInteger i = 0; i < 1000; i ++) {
BOOL isSuccess = [db executeUpdate:@"INSERT INTO myTable (name) VALUES (?)", @"will"];
if (!isSuccess) {
*rollback = YES;
break;
}else{
NSLog(@"success");
}
}
}];
- 或者拆解查询的数量,慢慢来