簡介
FMDB是對蘋果SQLite的封裝
多線程操作
1. 如果出現(xiàn)多個(gè)線程同時(shí)操作數(shù)據(jù)庫,怎么辦,用他,用他,F(xiàn)MDatabaseQueue
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. 大量查詢數(shù)據(jù)庫的情況
比如循環(huán)1000次執(zhí)行插入查詢的操作
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);
}
}];
}

image.png
結(jié)果發(fā)現(xiàn)按鈕一直處于被點(diǎn)擊狀態(tài),說明已經(jīng)阻塞了主線程,看了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);
發(fā)現(xiàn)他是用同步的方法進(jìn)行的操作,這樣就避免了多線程鎖死的情況,但是確定呢就是會(huì)阻塞主線程,所以,有如下解決方法:
- 在inDatabase的外面套了個(gè)異步,就不會(huì)阻塞主線程了
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);
}
}];
});
}

image.png

image.png
哈哈,就是線程有點(diǎn)多
- 用inTransaction事務(wù)方法查詢,會(huì)比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");
}
}
}];
- 或者拆解查詢的數(shù)量,慢慢來