试图理解为什么 @transactional(noROllBackFor .... 不起作用

Trying to understand why @transactional(noROllBackFor .... is not working

我有一些代码如下所示:

@Transactional(noRollbackFor = { CannotAcquireLockException.class, LockAcquisitionException.class })
public void deleteSomeData() {
    int backOffTime = 0;
    int fibonacci = 1;
    boolean executed = false;

    do {
        try {
            this.myDAO.deleteTheData();
            executed = true;
        } catch (RuntimeException rt) {
            int newBackoffTime = backOffTime + fibonacci;
            fibonacci = backOffTime;
            backOffTime = newBackoffTime;
            try {
                Thread.sleep(backOffTime * 100);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    } while (!executed);
}

这是在 Spring/JPA 环境中 运行ning。该代码由许多 Quartz 驱动的任务 运行 组成,这些任务在不同时间触发,有时同时触发。因此,如果抛出死锁异常,我试图通过在延迟后重新执行更新代码来解决数据库 (MySQL) 死锁。

我一直在尝试各种各样的事情并阅读了很多关于事务、死锁等的帖子

问题是,如果 this.myDAO.deleteTheData(); 抛出 CannotAcquireLockException,则事务被标记为需要回滚。我正在尝试做的是等待一段时间,然后再次尝试更新。然而,第二次尝试由于回滚状态而失败。因此,如果抛出此异常,我试图停止将事务设置为需要回滚。

我不确定我的头脑是否完全正确,而且这段代码无法正常工作。该事务仍被标记为需要回滚。

我可以将循环代码移到调用此方法的代码中,这将消除对事务的担忧,但是这将涉及大量重复代码执行,我想保留它尽可能靠近数据库。

关于我哪里出错了有什么建议吗?

阅读我原来的 post 上的答案后,我改用 Spring Retry 并且能够删除我所有的循环代码。该方法现在看起来像这样:

@Transactional
@ConcurrentDBUpdateRetryPolicy
public void deleteSomeData() {
    this.myDAO.deleteTheData();
}

使用定义我要使用的重试策略的自定义注释。您不需要执行自定义注释,但以这种方式执行它可以让您集中一个通用的重试定义。这是自定义注释:

@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Retryable(
   include = CannotAcquireLockException.class, 
   maxAttempts = 10, 
   backoff = @Backoff(delay = 500, maxDelay = 10000, multiplier = 2, random = true)
)
public @interface ConcurrentDBUpdateRetryPolicy {}

到目前为止,这一切都非常顺利。所以感谢提出建议的人,感谢 Spring Retry.

的作者