iOS6 上の Sqlite3 DB での DB 挿入を高速化するために、「BEGIN」および「END」コマンドで挿入をラップしています。DB はシリアル化モードで実行するように設定されています。興味深いのは、「END」を実行すると例外が発生することです。エラーは、DB がロックされていることを示しています。ええと、ロックされていることを期待しています。誰かがこの動作を引き起こす可能性のある条件を説明できますか?
2 に答える
問題が見つかりました。シリアライズされたアクセスを機能させるには、接続が 1 つしかない場合があります。私のテスト プロジェクトでは、接続キャッシュを実装するのを忘れていました。このようにして、各データベースにかなり多くの(開いている)接続ができました。
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);
}