我有一个用例,如下所述,我试图在SERIALIZABLE或REPEATALBE读隔离中使用transaction来完成它。
这是一个书店系统。最简单,没有用户管理和价格扣除限制。书店的数量与它一起。对于每个订单请求,我需要检查可用副本的数量,如果> 0,则减去1。
为此,我尝试使用transaction,其中i 1.读取book对象并获取count 2。如果count >0,则更新db中的count ( 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 boot处理。
这段代码哪里出了问题?配置是导致这种情况的原因吗?注意:使用spring-data-jpa,数据库: mysql
发布于 2020-03-17 01:29:24
使用InnoDB引擎解决了此问题。要更改引擎,请使用正确的方言。spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
MyIASM不支持事务。这就是为什么在上面的问题中没有创建事务的原因。Innodb支持事务和外键。
https://stackoverflow.com/questions/60630151
复制相似问题