に関する質問....C++ SQLiteの直列化されたモードでは、私はかなりの数ページを経た、そしてそれは考える起こっていただきましたが、[OK]アイデアを持っていますが、私は念のためにいくつかの質問を持っている
私のプログラムが使用しています-DTHREADSAFE = 1コンパイルオプション。ユーザーまたはネットワークからデータベース要求(選択、削除、挿入、更新)を受け取ったときにフォークし、子プロセスがさまざまなデータベースタスクを処理し、メッセージの中継が必要になるなど、
現時点では私のデータベースは並行性のためにセットアップされていませんが、それは大きな設計上の欠陥ですが、現時点ではポイントの横にあります。私のテーブルLEDGERのすべてのエントリを続き...
void PersonalDataBase::printAllEntries()
{
//get all entries
const char query [] = "select * from LEDGER";
sqlite3_stmt *stmt;
int error
try
{
if ((error = sqlite3_prepare(publicDB, query, -1, &stmt, 0)) == SQLITE_OK)
{
int ctotal = sqlite3_column_count(stmt);
int res = 0;
while (1)
{
res = sqlite3_step(stmt);
if (res == SQLITE_ROW)
{
Entry *temp = loadBlockRow(stmt);
string from, to;
from = getNameForHash(temp -> from);
to = getNameForHash(temp -> to);
temp -> setFromOrTo(from, 0);
temp -> setFromOrTo(to, 1);
temp -> printEntry();
printlnEnd();
delete temp;
}
else if (res == SQLITE_DONE || res==SQLITE_ERROR)
{
if (res == SQLITE_ERROR) { throw res; }
sqlite3_finalize(stmt);
break;
}
}
}
//problems
else
{
throw error;
}
}
catch (int err)
{
sqlite3_finalize(stmt);
setupOutput();
cout << "Database Error: " << sqlite3_errmsg(publicDB) << ", Error Code: " << (int) error << endl;
cout << "Did Not Find Values Try Again After Fixing Problems Above." << endl;
printlnEnd();
}
println("Done!");
}
- 私setupOutput()、printlnEnd()、のprintln()、私が好きなI/Oを、彼らが働く '非ブロッキング' キーボードの私の使用してすべてのヘルプは、ここではそれらについて心配しないですることができますそして今、この時点で私は4つのオプション...私のtry/catch周り
しばらくはその後、キャッチチェックで、ある把握ので
[OK]をcoutにだけ呼び出しと考えますもしerr = 5なら、私はsqlite3_busyをセットアップする必要があります_handlerを実行し、現在の操作をブロックしているものを待つ(一度SQLite_OKを返すと、古い変数すべてをクリーンアップしてから、もう一度やり直してください)、一度にこれらのうちの1つだけを設定できるようになりました。例えばChild1は大きな書き込みを行い、child2とchild3は最初の子の書き込みの上で並行して読み込みと更新を試みているため、この関数でSQLITE_BUSYが返された場合はエラーを出力し、whileループを再起動します関数)は、私の古いステートメントを完成させた後、作成された可能性のあるローカルオブジェクトをクリアしたのでしょうか?
私は再帰的なミューテックスを設定すべきですか?それはSQLite自身のロック機構にネジをかけて、一度に1つのデータベースに対して1つの操作しか許さないプロセス間で共有するように設定しますか?小規模な私のアプリケーションを使用するため、これはオプションの悪いように見えることはありませんが、再帰的なmutexの使用に関する多くの警告を読んでいて、これが最良のオプションかどうか疑問に思っています。排除あなた自身。しかし、私は同時読み込みをすることはできませんが、少し痛みです
オプション1を使用して、SQLiteのビジーハンドラを使用する代わりに、乱数でusleepを呼び出し、データをクリーンアップしている間に再起動しますか?
私のデータベースに関係する関数の前後には、それぞれ "BEGIN IMMEDIATE"/"COMMIT"を指定してsqlite3_exec()を使用し、それら2つの文の間のコードの間、データベースをロックします。私の "BEGIN IMMEDIATE"がBUSY(すべてが正しく設定されていれば唯一のものでなければなりません)を返すなら、SQLite_BUSYを返すことができるように(つまり少なくとも少なくとも)、私はsqlite3_busy_handlerを使用します。正直なところ、 1つのプロセスは一度にそれを使用することができます迷惑な...またはusleep()で乱数(おそらくこの数で1ミリ秒= 1秒のオーバラップの可能性がかなりスリムです)彼ら自身の目的のために無作為な間隔でデータベースをロックすることを絶えず試みるでしょう
良い方法はありますか?またはこれらのどれが一番良いか?(sqlite3_busy_timeout()でインストール)
しかし、2つのプロセスが 'sqlite3_busy_timeout()を呼び出すと、呼び出し元が元の呼び出し元と'衝突 'すると、SQLITE_BUSYが返されます。それに対処するハンドラ? データを変更するときにIMMEDIATEキーワードを使用するだけですか?ここでの問題は、somoneが現在行を読んでいて、別のプロセスがIMMEDIATEを呼び出すことに決めた場合、読者が終了するまで直ちにSQLITE_BUSYになるか、読んだりしなくなるかです。あたかもデータの読取り/印刷を中止したかのように、正直言って読取りトランザクションでさえもロックするのがベストでしょう – user1850434
WALモードは非常に興味深いですね! – user1850434
'sqlite3'コマンドラインシェル(' .timeout'もあります)を使ってIMMEDIATEロックをテストすることができます。 –