gpt4 book ai didi

c# - Quartz.NET + SQLite Jobstore 抛出 JobPersistenceException

转载 作者:行者123 更新时间:2023-12-01 22:29:38 29 4
gpt4 key购买 nike

当向调度程序添加或删除作业时,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 将 System.Data.SQLite 1.0.56 列为受支持的数据库提供程序,因此使用较新版本可能会出现问题。不过,我不认为可以选择从 1.0.66 返回,因为 IIRC 有很多改进/修复。
  • 我查看了 Quartz.NET 在 2.0.1 发行版修订版 (624) 和当前主修订版 (669) 之间的开发主干。似乎没有相关修复。
  • 我怀疑这是一个 System.Data.SQLite 问题。我偶然发现了几篇文章(涉及不同的 SQLite 版本),其中提到内部资源处理、保持数据库文件锁定可能存在一些问题。

补充2

目前,我已经放弃了。我尝试了很多事情,但开发还得继续。我切换到了另一种数据库类型(Firebird),到目前为止它似乎与 Quartz 配合得很好。

如果有人让这个工作正常,我很想听听。

-

异常详细信息:

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 脚本进行初始化

最佳答案

您必须在属性中将此项设置为 true:

properties["quartz.jobStore.txIsolationLevelSerializable"] = "true";

关于c# - Quartz.NET + SQLite Jobstore 抛出 JobPersistenceException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13745363/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com