@Transactional(isolation = Isolation.SERIALIZABLE, propagation = Propagation.REQUIRES_NEW) 没有按预期工作

@Transactional(isolation = Isolation.SERIALIZABLE, propagation = Propagation.REQUIRES_NEW) not working as expected

我有一个如下所述的用例,我试图在 SERIALIZABLE 或 REPEATALBE READ ISOLATION 中使用事务来完成。

这是一个书店系统。最简单,没有用户管理和价格扣除限制。书店用它来清点册数。 对于每个订单请求,我需要检查可用的份数,如果大于 0,则减去 1。

为此,我尝试使用我在其中进行的交易 1. 读取 book 对象并计数 2. 如果 count > 0 更新 db.

中的计数 ( count -1 )

这两项都必须在单个事务中完成以确认原子性/一致性。

我在我的 spring 启动服务中写了这个方法:

@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRES_NEW)
    @Override
    public Book updateBookQuantity(String isbn) {
        Book book = null;

        Optional<Book> bookRecord = bookRepository.findById(isbn);
        try {
            System.out.println("threadname on hold= " + Thread.currentThread().getId());
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("threadname resumed = " + Thread.currentThread().getId());

        if (bookRecord.isPresent()) {
            book = bookRecord.get();
            System.out.println("book count == " + Thread.currentThread().getId() + "  "+ book.getQuantity());

            if (book.getQuantity() > 0) {
                book = bookRecord.get();
                book.setQuantity(bookRecord.get().getQuantity() - 1);
                bookRepository.save(book);
            } else {
                throw new BookOutOfStockException(book.getTitle());
            }
        }
        return book;
    }

现在,当尝试使用 Rest api(同时点击 2 次)运行 时,我哪里出错了。两个线程 运行 并行,都将计数读取为 1 并将其更新为 0。 理想情况下,一个应该通过,另一个应该抛出 BookOutOfStockException 异常。 我没有配置任何特定于事务管理器的东西,它全部由 spring 引导处理。

这段代码哪里出错了?配置是这个的原因吗? 注意:使用 spring-data-jpa,数据库:mysql

使用 InnoDB 引擎解决了这个问题。要更换引擎,请使用正确的方言。 spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect

MyIASM 不支持事务。这就是为什么在上述问题中没有创建任何交易的原因。 Innodb 也支持事务和外键。