我有一个 iPhone 应用程序,它使用 sqlite 3.6(不使用 FMDB)来存储和加载数据。我在应用程序加载时加载数据库,并在整个应用程序中使用相同的数据库连接。
在后台线程中,应用程序从网络服务器下载一些数据并写入数据库。同时主线程也可能需要写入同一个数据库。这有时会导致 EXC_BAD_ACCESS,因为两个线程都试图访问数据库。
从不同线程使用数据库的最佳和最简单的方法是什么?
这是一个显示问题的示例:
sqlite3 *database;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:@"database.db"];
if (sqlite3_open([path UTF8String], &database) != SQLITE_OK) {
sqlite3_close(database);
return YES;
}
[NSThread detachNewThreadSelector:@selector(test) toTarget:self withObject:nil];
[self test];
return YES;
}
-(void)test {
for (int i = 0; i < 2000; i++) {
NSLog(@"%i",i);
sqlite3_exec([self getDb],"UPDATE mytable SET test=''", 0, 0, 0);
}
}
编辑:
在 willcodejavaforfood 下面的回答之后,我尝试更改我的代码,为每个单独的线程使用单独的数据库对象(连接),并且还添加了 sqlite3_busy_timeout() ,以便在数据库繁忙时 sqlite 将重试写入。现在我不再得到 EXC_BAD_ACCESS 但我注意到并非所有数据都被插入。所以这也不是一个稳定的解决方案。让 sqlite 与线程一起工作似乎真的很难..
我的新解决方案具有单独的连接:
-(void)test {
sqlite3 *db = [self getNewDb];
for (int i = 0; i < 2000; i++) {
NSLog(@"%i",i);
sqlite3_exec(db,"UPDATE mytable SET test=''", 0, 0, 0);
}
}
- (sqlite3 *)getNewDb {
sqlite3 *newDb = nil;
if (sqlite3_open([[self getDbPath] UTF8String], &newDb) == SQLITE_OK) {
sqlite3_busy_timeout(newDb, 1000);
} else {
sqlite3_close(newDb);
}
return newDb;
}
最佳答案
我通过使用一个线程和一个 NSOperationQueue 来插入数据解决了这个问题。我会考虑一下。我从来没有能够获得一个具有多线程的稳定系统,而且大多数写入并不那么重要,排队确实有帮助。
根据要求,更多信息:
我有一个 NSOperation
的子类,我用要存储的模型对象实例化它。
然后,这些操作被提交到在单独线程中运行的 NSOperationsQueue 扩展。这个自定义队列只是添加一个指向数据库实例的指针。执行操作时,它使用[NSOperationsQueue currentQueue]
属性来访问队列和数据库。我故意使用非并发操作(maxOperations 设置为 1)
因此,一次仅连续执行一个查询(或更新),完全在后台执行。
显然,完成后您需要某种回调。
这可能不是我能找到的最快但最稳定和最干净的解决方案。
文档:
http://developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationObjects/OperationObjects.html
http://www.cimgf.com/2008/02/16/cocoa-tutorial-nsoperation-and-nsoperationqueue/
http://icodeblog.com/2010/03/04/iphone-coding-turbo-charging-your-apps-with-nsoperation/
关于iphone - SQLite 和 iPhone SDK 的线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4338031/