iPhone中的sqlite3数据库被locking – 如何避免?

我有一个查询在Sqlite3数据库上执行search。 它什么也不做,只是用阅读器阅读。 对于每个find的匹配,它会调用更新结果视图的UI的callback。

当这个search正在运行的时候,我在UI中点击了一个button,在一个新的线程中执行一些其他的操作。 最后,它应该删除search控制器的视图,并显示一个新的控制器。

但是,在某个时刻触发的操作要写入数据库。 在那里,它只是挂起,最终我会看到数据库被locking的exception。

有趣的是,search读者也不会继续,这是一个僵局。

我是否需要以某种特殊的方式打开数据库来支持multithreading的使用? 连接的构造函数是什么?

MonoTouch 5.1+提供了一个API,可以让你select与SQLite一起使用的线程模型。

SqliteConnection.SetConfig (SQLiteConfig.MultiThread); 

这映射到SQLite库的一些连接选项 。

更新:如果您使用的是早期版本的MonoTouch(例如4.2和5.0.x之间),您可以使用附加到错误报告#652的二进制文件(按照说明)或复制粘贴修补程序(p / invoke和enum )在你自己的应用程序中。

我不知道我是否正确地解释了你的描述,但是你描述它的方式,在我看来,你的“阅读器”逐行地遍历数据库,并且每次find结果时,它都会callbackcallbackfunction? 它是否正确?

如果是这种情况,您可能会重复locking您的数据库,并且您的search将会很慢。

正确的方法是将所有匹配提取到一个查询中的结果集中 – 一旦查询完成,locking将被释放,并且从SQL获得的结果集只包含匹配的行。

你让SQLite通过使用“SELECT * FROM tablename WHERE columnX LIKE'%searchstring%'”types的查询来创build这样的结果集

(或类似,根据您的search条件)

这将创build一个包含数据库中所有匹配的结果集,然后释放数据库锁。 然后你可以遍历结果并创build对象,并将其放入与你的UI视图相连的NSArray。

 NSArray retval = [NSMutableArray array]; //Create a query NSString *query = [NSString stringWithFormat:@"SELECT * FROM %@ WHERE %@ LIKE %@", tableName, columnName, searchString]; sqlite3_stmt *statement; //Database locks here if (sqlite3_prepare_v2(_database, [query UTF8String], -1, &statement, nil) == SQLITE_OK) { //Database should unlock here, the query is finished while (sqlite3_step(statement) == SQLITE_ROW) { char *nameChars = (char *) sqlite3_column_text(statement, 0); NSString *name = [NSString stringWithUTF8String:nameChars]; SomeClass *info = [[SomeClass alloc] initWithName:name]; /* Extract other columns and put in your object */ [retval addObject:info]; [info release]; } sqlite3_finalize(statement); } else { NSLog(@"SQL-statement failed"); } 

这样做时,在需要时写入数据库应该没有问题。 只有在绝对必要时才对数据库执行新查询,例如,当您的search条件发生变化或数据库中的内容已更新时。

不要对未更改的数据库或未改变的search条件重复执行查询。