SQLiteデータベースに対して多数のINSERTを実行しています。私はただ1つのスレッドを使用しています。私はパフォーマンスを改善するために書き込みをバッチし、クラッシュの場合には少しのセキュリティを持っています。基本的には、私はたくさんのデータをメモリにキャッシュしておき、それが適切だと思うと、そのデータすべてをループしてINSERTを実行します。このためのコードは次のようになります。 SQLiteコミット中にデータベースファイルが不可能にロックされています
private void TryHandleCommit(SQLiteTransaction trans)
{
try
{
trans.Commit();
}
catch (Exception e)
{
Console.WriteLine("Trying again...");
this.TryHandleCommit(trans);
}
}
私はそうのように私のDBを作成します:
public void Commit()
{
using (SQLiteConnection conn = new SQLiteConnection(this.connString))
{
conn.Open();
using (SQLiteTransaction trans = conn.BeginTransaction())
{
using (SQLiteCommand command = conn.CreateCommand())
{
command.CommandText = "INSERT OR IGNORE INTO [MY_TABLE] (col1, col2) VALUES (?,?)";
command.Parameters.Add(this.col1Param);
command.Parameters.Add(this.col2Param);
foreach (Data o in this.dataTemp)
{
this.col1Param.Value = o.Col1Prop;
this. col2Param.Value = o.Col2Prop;
command.ExecuteNonQuery();
}
}
this.TryHandleCommit(trans);
}
conn.Close();
}
}
が、私は今、最終的に仕事をする事を取得するには、次のギミックを採用
public DataBase(String path)
{
//build connection string
SQLiteConnectionStringBuilder connString = new SQLiteConnectionStringBuilder();
connString.DataSource = path;
connString.Version = 3;
connString.DefaultTimeout = 5;
connString.JournalMode = SQLiteJournalModeEnum.Persist;
connString.UseUTF16Encoding = true;
using (connection = new SQLiteConnection(connString.ToString()))
{
//check for existence of db
FileInfo f = new FileInfo(path);
if (!f.Exists) //build new blank db
{
SQLiteConnection.CreateFile(path);
connection.Open();
using (SQLiteTransaction trans = connection.BeginTransaction())
{
using (SQLiteCommand command = connection.CreateCommand())
{
command.CommandText = DataBase.CREATE_MATCHES;
command.ExecuteNonQuery();
command.CommandText = DataBase.CREATE_STRING_DATA;
command.ExecuteNonQuery();
//TODO add logging
}
trans.Commit();
}
connection.Close();
}
}
}
次に、接続文字列をエクスポートして、プログラムのさまざまな部分で新しい接続を取得するために使用します。
一見無作為な間隔で、この問題を無視するかそれ以外の方法で解決するにはあまりにも速い速度ですが、未処理SQLiteExceptionが発生します。データベースファイルがロックされています。これは、トランザクションをコミットしようとしたときに発生します。それ以前にはエラーは発生していないようです。これはありません常にが発生します。時には全体が邪魔になることなく走ることもあります。
- コミットが完了する前に、これらのファイルに対する読み取りは実行されていません。
- 私は最新のSQLiteバイナリを持っています。
- .NET 2.0用にコンパイルしています。
- 私はVS 2008を使用しています。
- dbはローカルファイルです。
- このアクティビティはすべて1つのスレッド/プロセス内にカプセル化されています。
- ウイルス保護はオフです(ただし、ネットワーク経由で接続していた場合のみ有効です)。 Cに
- DBファイルを永続化するために設定され保存された
- ジャーナルモード:ドキュメント\ + Settings \のapplicationDataに
System.Windows.Forms.Application.AppData
ウィンドウが呼び出しを経由して - ない内部例外
- スコットランドのポストごとに、私は次の変更を実施してきたように 2つの別個のマシン(非常に似たハードウェアとソフトウェアですが)でも確認されています
- プロセスモニターを実行しています - 異質なプロセスがDBファイルにアタッチしていません - 問題は間違いなく私のコードです...
ここでは何が起こっているのでしょうか?
私はちょうどコードの混乱を落としてしまったことは知っていますが、私はあまりにも長くこのことを理解しようとしています。この質問の終わりまでそれを作る誰にも感謝します!
ブライアン
UPDATES:これまでに提案を
ありがとう!私は提案された変更の多くを実装しました。しかし私はそれが非決定論的である、我々は技術的に働く上...しかし...
コードを答えに近づいていることを感じます!中立のスピンから永遠に何かを行うことは保証されていません。実際には、1回目と10回目の繰り返しの間のどこかで動作するようです。合理的な期間のダメージで私バッチ私のコミットが軽減されますが、私は本当にこの状態で物事を残したくない場合は...
もっと提案を歓迎します!
コミットを小さくしたくはありませんが、begin tranを移動してtranを内側のバッチループにコミットするときに問題が発生しますか? – pjp