iPhone中的Sqlite3数据库被锁定 - 如何避免?

时间:2011-11-30 11:58:38

标签: objective-c ios multithreading sqlite xamarin.ios

我有一个在Sqlite3数据库上执行搜索的查询。除了使用阅读器阅读之外什么都不做。 对于每个找到的匹配,它会调用UI的回调来更新结果视图。

当此搜索正在运行时,我点击了UI中的一个按钮,该按钮将在新线程中执行其他操作。最后,它应该删除搜索控制器的视图并显示一个新的控制器。

但是,在某些时候触发的动作想要写入数据库。它只是挂起,最终我会看到数据库被锁定的异常。

有趣的是,搜索阅读器也没有继续,这是一个僵局。

我是否必须以某种特殊方式打开数据库以支持多线程使用?连接的构造函数是什么?

2 个答案:

答案 0 :(得分:1)

MonoTouch 5.1+提供API,让您选择与SQLite一起使用的线程模型。

SqliteConnection.SetConfig (SQLiteConfig.MultiThread);

这映射到SQLite库的一些连接options

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

答案 1 :(得分:1)

我不确定我是否正确地解释了您的描述,但是您描述它的方式,听起来我的“读者”逐行遍历数据库,每次找到结果时都会进行回调回调函数?这是对的吗?

如果是这种情况,您可能会反复锁定数据库,搜索速度会很慢。

正确的方法是在一个查询中将所有匹配提取到结果集中 - 一旦完成该查询,将释放锁定,并且您从SQL中获得仅包含匹配行的结果集。

让SQLite通过使用“SELECT * FROM tablename WHERE columnX LIKE'%searchstring%'”

类型的查询来创建这样的结果集。

(或类似的,取决于您的搜索条件)

这将创建一个包含数据库中所有匹配项的结果集,然后释放数据库锁。然后,您可以单步执行结果并创建对象并放入与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");
}

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

不要对未更改的数据库或未更改搜索条件的数据库运行重复查询。