1

iOS6 上の Sqlite3 DB での DB 挿入を高速化するために、「BEGIN」および「END」コマンドで挿入をラップしています。DB はシリアル化モードで実行するように設定されています。興味深いのは、「END」を実行すると例外が発生することです。エラーは、DB がロックされていることを示しています。ええと、ロックされていることを期待しています。誰かがこの動作を引き起こす可能性のある条件を説明できますか?

4

2 に答える 2

3

問題が見つかりました。シリアライズされたアクセスを機能させるには、接続が 1 つしかない場合があります。私のテスト プロジェクトでは、接続キャッシュを実装するのを忘れていました。このようにして、各データベースにかなり多くの(開いている)接続ができました。

于 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 に答える