我正面临一个奇怪的问题。我们已经搜索了这个bug两个星期了,不知道为什么会发生这种情况。
让我解释一下过程和情况。
我们有一个应用程序,它接收数据并将其存储在状态为“UPLOADED”的Postgres数据库中。一个单独的运行worker拾取此状态下的数据,并在计划作业中处理它。该进程从一些其他源获取数据并将它们添加到父实体。在数据已经被丰富之后,父实体将状态改变为“就绪”,并且在相同的过程中,父实体通过一些规则被评级。
如果评级是好的,则父实体是“接受”或“拒绝”,如果一些数据丢失,则父实体保持在状态“就绪”。在接受或拒绝的情况下,开始一些后续操作。
整个代码在Springs事务管理器管理的一个事务中运行
final var uploadedData = repository.findByStatus(ParentEntity.UPLOADED, PageRequest.of(0, 50, Sort.by("createdAt", "id").ascending()));
uploadedData
.forEach(parentEntity -> {
...
var processedParentEntity = parentEntity;
try {
processedParentEntity = transaction.execute(status -> {
analyze(parentEntity, retries.getOrDefault(parentEntity.getId(), 0) < maxTries);
return receiptRepository.findFirstById(parentEntity.getId()).get();
});
} catch (final TemporaryProblem temporaryProblem) {
...
} catch (final Exception exception) {
...
}
});
logger.info("finished parentEntity analysis");
问题是,在某些情况下,在某些条件下,parentEntity的数据被错误地持久化,尽管日志表明该实体处于正确的状态并具有正确的数据。在1..N关系中添加的每个子实体都被正确地持久化。未发生异常,也未回滚任何内容。
在超过99%的情况下,数据被正确地持久化,但在一些奇怪的情况下,parentEntity仍然处于“UPLOADED”状态,并且worker再次处理实体,这以后续问题结束。
我们可以看到这个问题可能与我们在5月份更新的Sping Boot 3有关。我们可以看到,当问题发生时,通常会有多个parentEntity连续受到影响,然后几个小时都不会发生问题。
任务在AWS fargate容器中运行,DB是托管RDS示例。我们进行了大量的集成测试,到目前为止,我们无法在本地环境中重现该问题。
1条答案
按热度按时间68de4m5k1#
今天终于找到bug了。它是一个星座,其中Web容器和worker查询附加到不同JVM实体管理器的同一实体。
当仅为读取请求的web请求和来自工作者的提交并发运行时,web容器的实体管理器检测到改变并更新所获取实体的完整页面,因此他覆盖改变。
我们将通过向父实体添加@Version来修复乐观锁定的错误。希望这能帮助我们解决这个问题。
更新
这个bug更容易修复。我们在一个简单的find方法中删除了错误引入的@Transactional。这导致对传递的实体执行update语句。