1

为了加快我在 iOS6 上的 Sqlite3 数据库上的数据库插入,我将插入包装在“BEGIN”和“END”命令中。数据库设置为以序列化模式运行。有趣的是,我在执行“END”时遇到了一个异常:错误说数据库被锁定。好吧,我希望它会被锁定,毕竟据我所知,我正在进行交易。有人可以解释什么条件会导致这种行为吗?

4

2 回答 2

3

我发现了问题。要使序列化访问工作,您可能只有一个连接。在我的测试项目中,我忘记实现连接缓存。这样,我最终为每个数据库获得了很多(打开的)连接。

于 2012-11-29T21:17:25.110 回答
0

它一定很简单,因为 BEGIN/END 命令没有什么花哨的。我努力重现您的问题(消除sqlite3_finalize、消除BEGIN等),但我做不到。我知道生成该错误的唯一方法是多次打开数据库或使用后台队列执行某些操作。

您必须与我们共享源代码。也许您正试图重新打开数据库?或者你在后台队列中有什么东西可以保存它?等等。

您提到以串行模式打开数据库。我是否从中推断出您有多个队列/线程进行数据库操作?我个人通过将我的数据库调用发送到的串行队列来序列化我的数据库操作,这保证了串行操作,因此我不必担心以特定模式打开数据库。也许您可以描述以串行模式打开数据库的基本原理。

但是,无论如何,这是一个直接使用调用的示例插入方法sqlite(尽管我承认我通常使用FMDB来消除这样的丑陋代码):

- (void)sqlInsert
{
    sqlite3_stmt *statement;
    sqlite3 *database = NULL;
    int rc;
    char *errmsg;

    if ((rc = [self openDatabase:&database]) != SQLITE_OK) // my open does the necessary parsing of the path, copying files, etc.
    {
        NSLog(@"%s database open error %d", __FUNCTION__, rc);
        return;
    }

    sqlite3_exec(database, "BEGIN", NULL, NULL, &errmsg);
    if (errmsg != NULL)
    {
        NSLog(@"%s exec BEGIN SQL error '%s'", __FUNCTION__, errmsg);
        sqlite3_free(errmsg);
    }

    const char *insertSql = "INSERT INTO CONTACTS (name, address, phone) VALUES (?, ?, ?)";

    if (sqlite3_prepare_v2(database, insertSql, -1, &statement, NULL) != SQLITE_OK)
        NSLog(@"%s prepare SQL error '%s' (%1d)", __FUNCTION__, sqlite3_errmsg(database), sqlite3_errcode(database));

    if (sqlite3_bind_text(statement, 1, [self.contactName.text UTF8String], -1, NULL) != SQLITE_OK)
        NSLog(@"%s bind contactName error '%s'", __FUNCTION__, sqlite3_errmsg(database));

    if (sqlite3_bind_text(statement, 2, [self.contactAddress.text UTF8String], -1, NULL) != SQLITE_OK)
        NSLog(@"%s bind contactAddress error '%s'", __FUNCTION__, sqlite3_errmsg(database));

    if (sqlite3_bind_text(statement, 3, [self.contactPhone.text UTF8String], -1, NULL) != SQLITE_OK)
        NSLog(@"%s bind contactPhone error '%s'", __FUNCTION__, sqlite3_errmsg(database));

    if (sqlite3_step(statement) == SQLITE_DONE)
        NSLog(@"%s Contact added", __FUNCTION__);
    else
        NSLog(@"%s step SQL error '%s' (%1d)", __FUNCTION__, sqlite3_errmsg(database), sqlite3_errcode(database));

    sqlite3_finalize(statement);

    sqlite3_exec(database, "END", NULL, NULL, &errmsg);
    if (errmsg != NULL)
    {
        NSLog(@"%s exec END SQL error '%s'", __FUNCTION__, errmsg);
        sqlite3_free(errmsg);
    }        

    sqlite3_close(database);
}
于 2012-11-29T18:15:48.600 回答