如何减少多库存、单笔交易或单笔交易?

How to reduce multi inventory, each transaction or only one transaction?

那样method1

@Transactional(rollbackFor = Exception.class)
public void reduce(list) {
    for (someone : list) {
        xxx
    }
}

method2

public void reduce(list) {
    for (someone : list) {
        reduceOne();
    }
}

@Transactional(rollbackFor = Exception.class)
private void reduceOne(one) {
    xxx
}

并发系统哪个更好?为什么? 如果选择method2,如何解决someone reduce fail?

两者各有优缺点

第一个选项为整个循环创建一个事务,因此如果列表中有 1000 个元素:

  1. 如果第1000个元素发生异常,则不会持久化所有999
  2. 如果没有发生异常,您将获得性能优势,因为您只创建了一个事务

对于第二个选项:

  1. 如果第1000个元素发生异常,则全部持久化999
  2. 然而,您为每个循环迭代创建一个事务,这会显着降低您的程序速度

就并发而言,这完全取决于您的 RBMS 的事务隔离级别。

例如对于Oracle来说,就是READ_COMMITTED,那么在一个线程更新行的情况下,不管更新的事务是否完成,其余的都可以自由读取这一行。因此,这两个选项的行为应该相似。

MySql 是 REPEATABLE_READ。因此,第一个选项可能会通过一个线程锁定许多行,从而阻止其余线程读取那些锁定的行。那样的话,第二个选项可能更好。

如您所见,影响因素很多,没有最佳答案。这取决于您使用的数据库、异常频率以及您的方法中 xxx 背后的内容。