无法在隔离的情况下执行事务 = 可在 Spring 引导中正确序列化 (postgreSQL)



我有一个spring-boot应用程序和postgreSQL数据库。我想做一个隔离为SERIALIZABLE或REPEATABLE_READ的事务。目标是更新一个名为product的特定实体,给定id和garantee,当事务运行时,其他人无法读取/更新/删除该实体。

我开发了下面的代码来测试这个例子的@Transactional(isolation=isolation.SERIALIZABLE(。我在findById(SELECT(save(UPDATE(

@Autowired
private IQueryProductRepository queryProductRepository;
@Autowired
private ICommandProductRepository commandProductRepository;    
@Override
public ResponseEntity updateProduct(String id) {
return ResponseEntity.ok(update(id, "name changed"));
}
@Transactional(rollbackFor = Exception.class, isolation = Isolation.SERIALIZABLE)
public Product update(String id, String name){
Optional<Product> optional = queryProductRepository.findById(id);
Product product = optional.get();
System.err.println(LocalDateTime.now() + " - SLEEP");
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.err.println(LocalDateTime.now() + " - WAKE");
product.setName(name);
product = commandProductRepository.save(product);
return product;
}
**Output:** 
2021-07-15T20:44:33.584670570 - SLEEP
2021-07-15T20:44:41.377932607 - SLEEP
2021-07-15T20:44:53.585632949 - WAKE
2021-07-15T20:45:01.378063371 - WAKE

预期第一事务锁定产品实体,并且第二事务仅能够在第一事务结束时更新。但结果并不是,当我执行第一个事务时;SLEEP";被打印并且它进入睡眠线程,并且当我在第一事务之后5秒执行第二事务时;SLEEP";立即打印,这意味着第二个事务可以访问该实体,而第一个事务尚未结束。

我不明白为什么会发生这种情况,因为我把隔离=隔离。可ERIALIZABLE?

我的应用程序属性文件:

spring.datasource.url=jdbc:postgresql://localhost:5432/cc
spring.datasource.username=root
spring.datasource.password=password
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.show-sql=true

这不是SERIALIZABLE隔离级别的工作方式。您所描述的或多或少是一个单用户系统。SERIALIZABLE隔离级别背后的思想是,它仍然允许并发,但确保并发事务不会相互干扰。如果多个事务的重叠不可串行化,即不能提供防止幻影读取的保证,则一个事务可能会失败。这只是一个外行的解释,但如果您想要一个单一用户执行,您将需要对共享对象进行某种悲观锁定。

最新更新