@Transactional(隔离=隔离.SERIALIZABLE,传播=传播.REQUIREDS_NEW)未按预期工作



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

这是一个书店系统。最简单,没有用户管理和价格扣除限制。这家书店有好几本书。对于每个订单请求,我需要检查可用副本的数量,如果大于0,则扣减1。

为此,我尝试使用交易1.阅读书籍对象并进行计数2.如果count>0,则更新数据库中的count(count-1(。

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

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

@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数据jpa,数据库:mysql

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

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

最新更新