2016-03-25 9 views
0

に関する質問....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周り

    1. しばらくはその後、キャッチチェックで、ある把握ので

[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()でインストール)

  • 答えて

    0

    のSQLiteの内部忙しいハンドラは、すでに倍の多かれ少なかれ乱数を眠ります。独自のハンドラを書く必要はありません。

    ランダムロックを使用するよりも、独自のロック機構を使用する方が効率的ですが、リーダー/ライターのロックがある場合にのみ有効です。

    BEGINまたはBEGIN IMMEDIATEは、同じトランザクション内の他の文がロックには実行できないことを保証しますが、書き込みを行うトランザクションにIMMEDIATEが使用されている場合のみです。

    同時リーダとライターを許可するには、WAL modeを使用することを検討してください。 (しかし、これは複数のライターを許可していません)

    +0

    しかし、2つのプロセスが 'sqlite3_busy_timeout()を呼び出すと、呼び出し元が元の呼び出し元と'衝突 'すると、SQLITE_BUSYが返されます。それに対処するハンドラ? データを変更するときにIMMEDIATEキーワードを使用するだけですか?ここでの問題は、somoneが現在行を読んでいて、別のプロセスがIMMEDIATEを呼び出すことに決めた場合、読者が終了するまで直ちにSQLITE_BUSYになるか、読んだりしなくなるかです。あたかもデータの読取り/印刷を中止したかのように、正直言って読取りトランザクションでさえもロックするのがベストでしょう – user1850434

    +0

    WALモードは非常に興味深いですね! – user1850434

    +0

    'sqlite3'コマンドラインシェル(' .timeout'もあります)を使ってIMMEDIATEロックをテストすることができます。 –

    関連する問題