1

スケジューラーにジョブを追加またはスケジューラーからジョブを削除すると、Quartz は散発的に JobPersistenceException をスローします (先行する SQLiteException に続いて)。

注目に値すると思われるもの:

  • Quartz.NET 2.01 + System.Data.SQLite 1.0.66 (執筆時点での両方の最新バージョンは、SQLite 1.0.82 のバイナリ パッケージが利用可能であることに気付きました)
  • 現在実行されているジョブ/トリガーがない場合も例外がスローされます (私は Quartz リスナーを監視しています)
  • ジョブは UI コンテキストから手動で追加されます (エラーを発生させるには約 10 ~ 20 回の繰り返しが必要ですが、完全にランダムに見えます)
  • AddJob()/DeleteJob() に触れない限り、すべてが正常に実行されているようです (複数のジョブ、並列実行、アプリケーションの再起動後の持続性)拡張テストの後、ジョブの追加/削除に関連していないと確信しています。データベースのロック/アクセスの問題は一般的な問題です。

ジョブを追加/削除するときに従わなければならない、私が認識していない推奨手順はありますか?

ISchedulerFactory の構成に問題はありますか? (下記参照)

補足

  • System.Data.SQLite 1.0.82 を使用してみましたが、事態が悪化しました。Quartz がジョブを実行するとすぐに、ほぼ常に「SQLite エラー (5): データベースがロックされています」というメッセージが表示されます。
  • Quartz.NET は、サポートされている db プロバイダーとして System.Data.SQLite 1.0.56 をリストしているため、新しいバージョンを使用すると問題が発生する可能性があります。ただし、IIRC には多くの改善/修正があったため、オプションとして 1.0.66 から戻ることは考えていません。
  • 2.0.1 リリース リビジョン (624) と現在のヘッド リビジョン (669) の間の Quartz.NET の開発トランクを調べました。関連する修正はないようです。
  • System.Data.SQLite の問題だと思います。DBファイルをロックしたまま、リソースの内部廃棄に問題がある可能性があると言及している(さまざまなSQLiteバージョンに関する)いくつかの投稿に出くわしました。

補足 2

とりあえず、これは諦めました。私は多くのことを試しましたが、開発は続けなければなりません。これまでのところ Quartz で問題なく動作するように見える別のデータベース タイプ (Firebird) に切り替えました。

誰かがこれを機能させたら、とにかくそれについて聞きたいです。

-

例外の詳細:

Quartz.JobPersistenceException: "ADO.NET トランザクションをコミットできませんでした。データベース ファイルがロックされています\r\nデータベースがロックされています"

スタック

bei Quartz.Impl.AdoJobStore.JobStoreSupport.CommitConnection(ConnectionAndTransactionHolder cth, Boolean openNewTransaction)
bei Quartz.Impl.AdoJobStore.JobStoreSupport.ExecuteInNonManagedTXLock(String lockName, Func`2 txCallback)
bei Quartz.Impl.AdoJobStore.JobStoreTX.ExecuteInLock(String lockName, Func`2 txCallback)
bei Quartz.Impl.AdoJobStore.JobStoreSupport.RemoveJob(JobKey jobKey)
bei Quartz.Core.QuartzScheduler.DeleteJob(JobKey jobKey)
bei Quartz.Impl.StdScheduler.DeleteJob(JobKey jobKey)

InnerException SQLiteException: "データベース ファイルがロックされています\r\nデータベースがロックされています"

スタック

bei System.Data.SQLite.SQLite3.Step(SQLiteStatement stmt)
bei System.Data.SQLite.SQLiteDataReader.NextResult()
bei System.Data.SQLite.SQLiteDataReader..ctor(SQLiteCommand cmd, CommandBehavior behave)
bei System.Data.SQLite.SQLiteCommand.ExecuteReader(CommandBehavior behavior)
bei System.Data.SQLite.SQLiteCommand.ExecuteNonQuery()
bei System.Data.SQLite.SQLiteTransaction.Commit()
bei Quartz.Impl.AdoJobStore.JobStoreSupport.CommitConnection(ConnectionAndTransactionHolder cth, Boolean openNewTransaction)

例外のソースは「cth.Transaction.Commit();」です。この Quartz.NET メソッドで。

/// <summary>
/// Commit the supplied connection.
/// </summary>
/// <param name="cth">The CTH.</param>
/// <param name="openNewTransaction">if set to <c>true</c> opens a new transaction.</param>
/// <throws>JobPersistenceException thrown if a SQLException occurs when the </throws>
protected virtual void CommitConnection(ConnectionAndTransactionHolder cth, bool openNewTransaction)
{
    CheckNotZombied(cth);

    if (cth.Transaction != null)
    {
        try
        {
            IsolationLevel il = cth.Transaction.IsolationLevel;
            cth.Transaction.Commit();
            if (openNewTransaction)
            {
                // open new transaction to go with
                cth.Transaction = cth.Connection.BeginTransaction(il);
            }
        }
        catch (Exception e)
        {
            throw new JobPersistenceException("Couldn't commit ADO.NET transaction. " + e.Message, e);
        }
    }
}

これは、ISchedulerFactory を作成する方法です。

public static ISchedulerFactory CreateSQLiteSchedFactory(SQLiteConnection sqlConn, string tablePrefix) {
    // db provider hinzufügen
    var metaData = new DbMetadata();
    metaData.AssemblyName = "System.Data.SQLite,Version=1.0.66.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139";
    metaData.BindByName = true;
    metaData.CommandBuilderType = typeof(SQLiteCommandBuilder);
    metaData.CommandType = typeof(SQLiteCommand);
    metaData.ConnectionType = typeof(SQLiteConnection);
    metaData.ExceptionType = typeof(SQLiteException);
    metaData.ParameterDbType = typeof(TypeAffinity);
    metaData.ParameterDbTypePropertyName = "DbType";
    metaData.ParameterNamePrefix = "@";
    metaData.ParameterType = typeof(SQLiteParameter);
    metaData.UseParameterNamePrefixInParameterCollection = true;
    DbProvider.RegisterDbMetadata("SQLite-1066", metaData);

    // konfiguration für factory erstellen
    NameValueCollection properties = new NameValueCollection();
    properties["quartz.scheduler.instanceName"] = "TestScheduler";
    properties["quartz.scheduler.instanceId"] = "instance_one";
    properties["quartz.threadPool.type"] = "Quartz.Simpl.SimpleThreadPool, Quartz";
    properties["quartz.threadPool.threadCount"] = "5";
    properties["quartz.threadPool.threadPriority"] = "Normal";
    properties["quartz.jobStore.misfireThreshold"] = "60000";
    properties["quartz.jobStore.type"] = "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz";
    properties["quartz.jobStore.useProperties"] = "false";
    properties["quartz.jobStore.dataSource"] = "default";
    properties["quartz.jobStore.tablePrefix"] = tablePrefix;
    properties["quartz.jobStore.clustered"] = "true";

    properties["quartz.jobStore.lockHandler.type"] = "Quartz.Impl.AdoJobStore.UpdateLockRowSemaphore, Quartz";

    properties["quartz.dataSource.default.connectionString"] = sqlConn.ConnectionString;
    properties["quartz.dataSource.default.provider"] = "SQLite-1066";

    // factory erzeugen
    return new StdSchedulerFactory(properties);
}

SQLiteConnection は、「Data Source=c:\mydb.db;Version=3;」のような接続文字列で作成されます。すべての Quartz テーブルは、提供された SQL スクリプトを使用して初期化されます

4

2 に答える 2

1

このエラーの原因は、SQLite データベースでの複数の同時書き込みが原因である可能性が最も高く、sqlite は複数の読み取り専用接続のみを受け入れることができますが、同時に書き込みを受け入れることはできません!

http://www.sqlite.org/faq.html#q5

于 2012-12-06T14:18:22.060 に答える