java - 服务同时调用两次

标签 java spring transactional

我使用 Spring 用 Ja​​va 编写了以下 Web 服务,我用 @Transactional 注释封装了它,以确保我们可以在需要时回滚。

它工作正常,除了服务被调用两次的情况,第二次调用发生在第一次调用完成之前。

在这种情况下,由于第一个事务仍在运行并且尚未提交到数据库,因此第二个事务将执行完整方法,插入重复行,再次更新状态,然后调用 sendAlert()。

这是伪代码。

@Transactional
public ServiceResponse update(ServiceRequest serviceRequest) {
....
if (myDao.getStatus() == "COMPLETE") {
 return serviceError;
}
 myDao.insertRow();
 myDao.updateStatus("COMPLETE");
 sendAlert();
}

如何防止第二笔交易在第一笔交易之前完成?将隔离级别设置为未提交读不是一个选项,因为数据库不支持它。

最佳答案

根据您的问题,我假设 update(..) 将在某种程度的并发下被调用。

我发现这种使用外部数据存储进行协调的方法存在一些问题。对于默认的“已提交读”隔离,您将遇到现在所遇到的情况,但是,即使您可以使用“读未提交”,您也会遇到一个问题:第二个事务读取了脏的“COMPLETE”数据,返回,但第一个事务可能仍然失败并回滚。

我提出了几种方法(当然我做了很多假设)

  1. 幂等性:通过使数据库更新具有幂等性,您不必担心重复更新
  2. 压缩:如果有可能最新的记录总是正确的,您可以让所有写入通过,但只读取最新的记录,这类似于 Kafka 内部压缩的方式

关于java - 服务同时调用两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55597661/

相关文章:

java - Exception 类中有成员变量

java - @Transactional注解是否避免并发访问业务层方法

java - 如何覆盖java中的泛型列表返回类型

java - VM 初始化期间发生错误 : Could not reserve enough space for object heap

Java Spring Web App - 数据库访问异常

java - Spring 。 "schemaLocation ... must have even number of URI' 秒”

java - BindingResult 和 bean 名称 'configId' 的普通目标对象都不能用作请求属性 Jasper 异常

java - 尝试加载不同的属性以进行 Spring Boot 应用程序的 Cucumber 集成测试?

Spring @Transactional rollbackFor 不起作用

java - Sonar 误报问题