2017-11-13 17 views
1

私はSQLiteを使用するマルチスレッドのC#プログラムを開発中です。私はいくつかの行を更新するためにSQLiteCommand.ExecuteNonQuery()を実行すると "SQLite error(5):データベースがロックされている"という文句があるという問題があります。私は、挿入や更新が行われている間にデータベースがロックされるため、DBを変更する別のクエリが2番目のクエリに来ると、このデータベースがロックされたエラーが発生するため、この問題が発生することを認識しています。だから私はそれに回避策を実装しようとしているが、私はそれをどうすればいいのか分からない。SQLite DBがロックされているかどうかを検出するには?

データベースロックエラーがスローされた場合、プログラムは少し待ってから動作するまで再試行するようにしていました。しかし、何らかの例外がキャッチされ、データベースロックされたメッセージがまだデバッグ出力に出力されても、コードはtry-catchブロックを終了します。私は、SQLクエリーが拒否されるか受け入れられるかは完全にはわかりません。

また、私はTransactionScopeを使ってみましたが、それ以来ロックされていませんでしたが、問題のランダムな性質のため、実際に問題が解決した場合は100%確信できません。ある程度までしかないか、そうでなければ私はこれまでのところ幸運だった。

SQLiteConnection connection = new SQLiteConnection("Data Source=DB.db;Version=3;"); 
connection.Open(); 
SQLiteCommand command = connection.CreateCommand(); 
command.commandText = inputQuery; 
try 
{ 
    command.executeNonQuery(); 
} 
catch (SQLiteException sqle) 
{ 
    Debug.WriteLine("Database error: " + e.Message); 
    return false; 
} 
catch (Exception e) 
{ 
    Debug.WriteLine("Database error: " + e.Message); 
    return false; 
} 
finally 
{ 
    connection.Close(); 
} 

だから私は本当に1)データベースを解消する方法を見つける私を助けるために誰かのようにDBがエラーが発生したロックされているかどうかを検出するための方法に問題または2)をロックされていると思います。前もって感謝します。

+0

SQLiteのドキュメント私は(、適切なロック、同期プリミティブ、または非同期パターンのいずれかで)生産者 - 消費者パターンを使用して、単一のスレッドですべてのSQLiteの操作を行うお勧めします。おかげさまで – Dai

+0

ありがとうございます。これは、DBロックを完全に排除するための最も安全なアプローチと思われます。 – JonH

答えて

0

エラーコード5(ビジー状態)が発生している場合は、即時トランザクションを使用してこれを制限できます。即時トランザクションを開始できる場合、SQLiteはコミットするまでビジーエラーを受け取らないことを保証します。

SQLiteには行レベルのロックがありません。データベース全体がロックされます。 WALジャーナルを使用すると、1人のライターと複数のリーダーができます。他のジャーナリング方法では、1つのライターまたは複数のリーダーを持つことができますが、両方を同時に使用することはできません。 「SQLITE_BUSY」

+0

ありがとうございます。即時取引とは何ですか? BTWは現在、SQLiteConnection.BeginTransaction()は推奨されていないと言われているので、TransactionScopeを使用していますが、より広範に使用されているように思われるので、BeginTransactionへの変更を検討しています。 – JonH

+0

Nvm、私はBEGIN IMMEDIATEを見つけました。 BEGIN IMMEDIATE部分のアルゴリズムを試し続けることができるので、これは間違いなく私を助けます。しかし、C#のBEGIN IMMEDIATEの使い方についてはわかりません。 – JonH

関連する問題