1

我们正在评估spring batch(3.0.3版),为此我们做了一个简单的数据处理

我们的测试:

我们在一个表中有 500k 行,我们想要处理它,将一个字段更新为“行已处理”的标志

我们的工作定义是这样的:

<beans:beans xmlns="http://www.springframework.org/schema/batch"
    xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/batch
        http://www.springframework.org/schema/batch/spring-batch.xsd"
    profile="job1">

    <job id="job1">
        <step id="step1">
            <tasklet>
                <chunk reader="itemReader"  writer="itemWriter"
                    commit-interval="#{jobParameters['commit.interval']?:'100'}" />     
            </tasklet>
        </step>
    </job>

我们使用 JdbcCursorItemReader 作为读取器(查询如 SELECT field1, field2 FROM table WHERE field3 = '2Process')和 JdbcBatchItemWriter 作为写入器(更新表 SET field3 = 'Processed' WHERE field1 = :field1 和 field2 = :field2)

我们的数据库是一个 DB2/zOS,在我们使用的表中按页配置了锁

我们使用 Bitronix 作为事务管理器

当我们启动它时,我们会得到这个异常:

Caused by: com.ibm.db2.jcc.am.SqlException: Error for batch element #8: DB2 SQL Error: SQLCODE=-913, SQLSTATE=57033, SQLERRMC=00C9008E;00000302;DBABCD  .TSTABLE .X'000201', DRIVER=4.19.26

似乎发生异常是因为读取器的 Tx 与数据库写入器的 Tx 不同。我们在第 201 页有一个块。

显然,如果我们改变select的隔离级别,加上ur,批处理就ok了。

我们的问题是,这个数据库锁可能是事务管理器的问题,因为 bitronix 不支持嵌套事务?或者似乎是db2数据库和定义的锁定策略有问题

此外,我们不知道是否有一个好的做法是使用一个包含读取和写入同一个表的步骤的 spring 批处理

编辑:对不起,你是对的,我的解释中有很大的错误,db2/zOS

4

1 回答 1

2

首先您好,因为在执行更新密集操作(例如批处理)时,您有页面锁定而不是行锁定。陷入僵局是不可避免的。所以你只能接受它。您需要做的是创建能够以良好方式容忍它的架构。

首先,我强烈建议您从页面锁定切换到行锁定。页面锁定的真正想法是为极度读取密集型应用程序启用数据库。我严重怀疑您的应用程序是这样的,这意味着行锁定将呈现的小开销对于它将呈现的 conviniese 而言是可以忽略不计的权衡。

但是让我们假设您不切换页面锁定您的替代方案是什么,以便将死锁减少到最低限度:

  1. 缩小页面大小!
  2. 随机播放记录。例如,如果您使用 10 个线程,则不要使批处理顺序成为 IDS,使第一个线程每 10 条记录选择一次,而线程每 9 条记录选择一次。当您选择读者时,最好按一些随机因素对其进行排序。
  3. 使用批处理,但不要批处理多条记录。您可以尽可能减小块大小。这样,您将减少整体锁定因子。

基本上,无论您做什么,您都需要考虑如何确保我的交易尽可能短,并尽可能多地访问不同的页面。

但是即使那样你也不能保证至少没有遇到一个死锁。这意味着您需要实现 RETRY 逻辑。这是强制性的。

最后,您只需为自己省去所有这些麻烦并将 DB2 配置为行锁定。

如果是我,我可能会将块大小设置为 1-2-3 之类的东西,但绝对不是 100。

于 2018-03-02T13:16:08.340 回答