0

最近、作業中の iOS アプリケーションの sqlcipher sqlite3 データベースに対するすべてのデータベース呼び出しにトランザクションを追加しましたBEGINCOMMIT

私は次の方法でこれを行っています:

#define kTRANSACTION_BEGIN @"BEGIN"
#define kTRANSACTION_COMMIT @"COMMIT"

-(void)transactionBegin
{
    int status = sqlite3_exec(self.Database, kTRANSACTION_BEGIN.UTF8String, NULL, NULL, NULL);
    NSLog(@"BEGIN Status = %i", status);
}

-(void)transactionEnd
{
    char* errorMessage;
    int status = 0;

    status = sqlite3_exec(self.Database, kTRANSACTION_COMMIT.UTF8String, NULL, NULL, &errorMessage);
    NSLog(@"COMMIT Status = %i", status);

    if (status != SQLITE_OK) {
        NSLog(@"ERROR: SQL Error closing transaction (%i):  %s\n %s",status, errorMessage ,sqlite3_errmsg(self.Database));
    }
}

これらのメソッドは、オープン (および PRAGMA の設定) 後、データベース接続をクローズする前に直接呼び出されます。

これらは両方とも正常に実行されているように見えます。ただし、データベースの場所を調べると、db.sqlite ファイルは 0 バイトのままで、db.sqlite-journal ファイルは 512 バイトです。データベースに対して実行されるクエリは、アプリが閉じられるまで正常に実行され続け、その後、挿入されたすべてのデータが失われます。orステートメントをディスクにCOMMIT永続化しないのはなぜですか?CREATE TABLEINSERT

ドキュメントを読んだ後、明示的に設定しない限りjournal_mode、sqlite データベースの を に設定する必要があるようDELETEです。これが本当なら、コミットが完了した後は -journal ファイルはもうないはずです。これをテストできる c API を使用する方法はありますか?

また、データベース ラッパーを使用していくつかの異なるデータベース ファイルを操作しているため、コードが正常に機能していると信じるようになりました。トランザクションの開始とコミットが正常に完了すると、BEGIN および COMMIT ステータス コードは常に 0 になり、これはSQLITE_OK. この奇妙な動作は、変更を試みる前にレコードを 1 つだけ挿入した場合にのみ発生しCOMMITます。

デフォルトの sqlite 構成から変更した唯一の他のオプションは、ページ サイズ ( PRAGMA cipher_page_size = 4096) です。ページ サイズは、私がこのラッパーで使用している他のいくつかの大規模データベースのパフォーマンスを向上させるために調整されています。ページ サイズへの変更を削除しても、問題は解決しません。

最後に、トランザクションをまとめて削除すると、この問題はまったく発生しないことに気付きました。できれば、パフォーマンスを向上させるためにトランザクションを残したいと思いますが、データを永続化しないと、データベースの目的が損なわれます。

なぜこれが起こっているのか、または私が試すことができる他の何かについて誰かが考えを持っていますか?

前もって感謝します。

4

0 に答える 0