同时更新特定 db-table-row-column 的最佳做法是什么?

What's the best practice to update a specific db-table-row-column simultaneously?

db中的行列(如果该行不存在,应先创建它。) 可以被多个用户同时更新,更新的最佳做法是什么高效正确地划船?

模特

@Entity(table = "counters")
public class Counter {

    @Id
    public Long id;

    /**
     * <b>count</b> and can be updated by users simultaneously and frequently. count is
     * very important, every updates should be success without lost updates.
     */
    public int  count;
}

可能的解决方案:

1) 使用同步关键字

public static synchronized void createOrUpdateCount(int counterId, int increments) {
    Counter counter = Counter.findById(counterId);
    if(counter == null) {
        counter = new Counter();
        counter.count = increments;
    } else {
        counter.count += increments;
    }
    counter.saveToDb();
}

2) 使用乐观锁,出现乐观异常时重试更新

public static createOrUpdateCount(int counterId, int increments) {
    try {
        doCreateOrUpdateCount(counterId, increments);
    } catch (OptimisticLockException e) {
        // retry updating on optimistic exception, maybe several times will be 
        // tried until updating succeed.
        doCreateOrUpdateCount(counterId, increments);
    }
}

private static void doCreateOrUpdateCount(int counterId, int increments) {
    Counter counter = Counter.findById(counterId);
    if(counter == null) {
        counter = new Counter();
        counter.count = increments;
    } else {
        counter.count += increments;
    }
    counter.saveToDb();
}

3) 将事务隔离级别设置为可序列化。

@Transactional(isolation = TxIsolation.SERIALIZABLE)
public static void createOrUpdateCount(int counterId, int increments) {
    Counter counter = Counter.findById(counterId);
    if(counter == null) {
        counter = new Counter();
        counter.count = increments;
    } else {
        counter.count += increments;
    }
    counter.saveToDb();
}

您的最佳实践是什么?任何建议将不胜感激。

我认为您需要查看您正在使用的特定数据库。大多数都有某种类型的 'upsert' 语句,可以作为单个 sql 语句执行插入或更新。然后您需要检查与此相关的数据库特定文档,特别是您正在检查是否可以通过编写存储过程来改进它(并明确选择首先执行最常见的操作,例如更新然后插入与插入然后更新)。

与使用存储过程或特定于数据库的 'upsert' 或 'merge' 语句相比,在 ORM 级别执行此操作很可能效果不佳。