【问题标题】:Deadlock while running multiple instances of a spring batch job运行弹簧批处理作业的多个实例时出现死锁
【发布时间】:2021-06-09 04:17:18
【问题描述】:

我有一个 spring 批处理作业,它在基于块的步骤中从数据库读取并在进行一些处理后写入文件。 我的要求是同时运行几乎 16 个作业实例,只是使用不同的作业参数。

但我在这样做的过程中遇到了几个问题。

1.

无法为事务打开 JDBC 连接。嵌套异常是 java.sql.SQLTransientConnectionException: Hikaripool -1 - Connection is not available。

异常:无法增加标识。嵌套异常是 com.microsoft.SQLserver.jdbc.SQLServerException: Transaction (process ID 124) was deadlocked on lock resources with other process,并已被选为死锁牺牲品。重新运行事务。

我已经尝试了链接Github link 中提供的解决方案,方法是设置IsolationLevel 并更改元数据表,如下所示。

像这样设置 IsolationLevelForCreate

JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
factory.setIsolationLevelForCreate("ISOLATION_REPEATABLE_READ");

让 DBA 像这样为每个 SEQ 表添加索引(JET 是我将 repo 表放入的架构):

ALTER TABLE [JET].[BATCH_JOB_EXECUTION_SEQ]
ADD CONSTRAINT [BATCH_JOB_EXECUTION_SEQ_PK] PRIMARY KEY CLUSTERED ([ID] ASC)
GO

ALTER TABLE [JET].[BATCH_JOB_SEQ]
ADD CONSTRAINT [BATCH_JOB_SEQ_PK] PRIMARY KEY CLUSTERED ([ID] ASC)
GO

ALTER TABLE [JET].[BATCH_STEP_EXECUTION_SEQ]
ADD CONSTRAINT [BATCH_STEP_EXECUTION_SEQ_PK] PRIMARY KEY CLUSTERED ([ID] ASC)
GO

但我仍然面临这个问题。

PS:spring batch已经部署到AKS(Azure Kubernetes Services),使用Azure SQLServer作为数据源。

【问题讨论】:

  • 要调查死锁,您检查死锁图,它会告诉您哪些资源导致了死锁,这通常足以解决如何修复它。否则,您只是在猜测并希望中奖。此外,您很可能无法消除所有死锁,在这种情况下需要重试系统。

标签: sql-server spring database spring-boot spring-batch


【解决方案1】:

根据https://github.com/spring-projects/spring-batch/issues/1448 中的讨论,该问题似乎是由Spring Framework 中的SqlServerMaxValueIncrementer 未使用SQLServer 的本机序列引起的。以下是 Javadoc 的摘录:

There should be one sequence table per table that needs an auto-generated key.

Example:

create table tab (id int not null primary key, text varchar(100))
create table tab_sequence (id bigint identity)
insert into tab_sequence default values

这可能是由于 SQLServer 直到最近才支持序列。但我想这就是 Spring Batch 将tables to emulate sequences 用于 MS SQL Server 的原因。

我建议您尝试更改the default DDL 以使用序列而不是表格:

CREATE SEQUENCE BATCH_STEP_EXECUTION_SEQ ;
CREATE SEQUENCE BATCH_JOB_EXECUTION_SEQ ;
CREATE SEQUENCE BATCH_JOB_SEQ ;

这是基于 MS SQL Server 的docs 的默认序列定义。这应该可以,但您可以根据需要自定义它们。

您可能还需要提供基于序列的自定义 DataFieldMaxValueIncrementer(因为 Spring Framework 中的序列使用表)并通过 DataFieldMaxValueIncrementerFactory 将其注册到 Spring Batch 中(请参阅 JobRepositoryFactoryBean#setIncrementerFactory)。

【讨论】:

    猜你喜欢
    • 2017-11-03
    • 1970-01-01
    • 2021-11-15
    • 2015-04-18
    • 2020-07-10
    • 2015-05-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多