Spring Boot 事务隔离级别READ_UNCOMMITTED不起作用

Spring Boot Transaction Isolation level READ_UNCOMMITTED not working

提问人:vipvipul1 提问时间:8/29/2023 更新时间:8/29/2023 访问量:23

问:

我正在尝试在 spring boot 项目的 REST API 中实现隔离级别READ_UNCOMMITTED。以下是控制器和服务。

工单Con.java

@RestController
@RequestMapping("/ticket/book/")
public class TicketCon {
    @Autowired
    private TicketSer ticketSer;
 
    @PostMapping("/1")
    public ResponseEntity<?> bookTicket1(@RequestBody TicketRequestDto ticketRequestDto) throws InterruptedException {
        ticketSer.bookTicket1(ticketRequestDto.getShowSeats());
        return ResponseEntity.ok("");
    }
 
    @PostMapping("/2")
    public ResponseEntity<?> bookTicket2(@RequestBody TicketRequestDto ticketRequestDto) throws InterruptedException {
        ticketSer.bookTicket2(ticketRequestDto.getShowSeats());
        return ResponseEntity.ok("");
    }
}

售票服务.java

@Service
public class TicketSer {
    @Autowired
    private ShowSeatRepository showSeatRepository;
 
    @Transactional(isolation = Isolation.READ_UNCOMMITTED)
    public void bookTicket1(List<Long> showSeatsIds) throws InterruptedException {
        System.out.println("Reading Show Seats.");
        List<ShowSeat> showSeats = showSeatRepository.findAllByIdIn(showSeatsIds);
        showSeats.forEach(System.out::println);
 
        showSeats.forEach(s -> s.setShowSeatStatus(ShowSeatStatus.LOCKED));
        showSeatRepository.saveAll(showSeats);
        System.out.println("Show Seats LOCKED. Not Committed yet.");
        
        Thread.sleep(20000);
        System.out.println("Show Seats LOCKED. Will be Committed.");
    }
 
    @Transactional(isolation = Isolation.READ_UNCOMMITTED)
    public void bookTicket2(List<Long> showSeatsIds) throws InterruptedException {
        System.out.println("Reading Show Seats.");
        List<ShowSeat> showSeats = showSeatRepository.findAllByIdIn(showSeatsIds);
        showSeats.forEach(System.out::println);
    }
}

最初,所有 ShowSeat 实体的数据库中都有 ShowSeatStatus=“AVAILABLE”。

首先,我正在执行 ticket/book/1 API,这将使所有传递的 showSeatsIds 的 ShowSeatStatus=“LOCKED” 进入睡眠状态 20 秒,而无需在数据库中提交。

然后,在 5 秒后(在第一个事务提交之前),我正在执行 ticket/book/2 API,它正在读取传递的相同 showSeatsIds。

我希望第二个 API 的输出将传递的 showSeatIds 的 ShowSeatStatus 打印为“LOCKED”,因为这是脏读(未提交)数据。但这并没有发生。我看到这些showSeatIds的输出为“AVAILABLE”。

我哪里错了? 请帮忙。

多线程 spring-data-jpa spring-transactions transaction-isolation

评论

0赞 Panagiotis Kanavos 8/30/2023
不要使用READ_UNCOMMITED。它不能解决任何问题。如果由于锁定而出现性能问题,请修复它们,而不是试图掩盖它们
0赞 Panagiotis Kanavos 8/30/2023
go to sleep state for 20 seconds without committing in database.这本身就是一个错误。是否尝试将数据库用作队列?哪个数据库?这很重要。使用表作为队列很复杂,很大程度上取决于数据库的锁定模型。通常,它涉及更严格的锁定,并且从不 READ_UNCOMMITTED
0赞 M. Deinum 8/30/2023
您使用的是 JPA,内存中的状态只会在执行提交时同步到数据库(除非您显式刷新)。接下来是哪个数据库,因为并非所有数据库都支持所有隔离级别。
0赞 vipvipul1 8/30/2023
我正在使用MySql数据库。我的实际要求是读取其他事务正在完成的 ShowSeat 实体上的未提交数据。

答: 暂无答案