【问题标题】:Use Transactions for Synchronization in Spring在 Spring 中使用事务进行同步
【发布时间】:2019-04-11 07:31:13
【问题描述】:

我们有一个可以读写MySql的方法,该方法可以被多个线程调用。 db 操作如下:

public List<Record> getAndUpdate() {
    Task task = taskMapper.selectByPrimaryKey(id);
    if (task.getStatus() == 0) {
        insertRecords();
        task.setStatus(1);
        taskMapper.update(task);
    } 

    // some queries and return data
    return someRecordMapper.selectByXXX();
}

private void insertRecords() {
    // read some files and create someRecords
    someRecordMapper.insertBatch(someRecords);
}

该方法读取任务的状态,如果状态为0,则将(该任务的)一堆记录插入Records表,然后将任务的状态设置为1。

我希望这些数据库操作是事务性的和独占的,这意味着当一个线程进入事务时,其他线程试图读取相同的 任务应该阻塞。否则,他们将看到任务状态为 0,并且会多次调用insertRecords(),从而导致重复数据。

@Transactional 注释似乎不会阻止来自其他线程的事务,它只确保在中止的情况下回滚。所以我认为仅凭@Transactional,上述问题是无法避免的。

我用的是MySql和mybatis,我觉得MySql本身可以实现这样的线程间同步,所以我尽量不引入redis lock等额外的组件来做。我想知道我如何在 Spring 中做到这一点?

【问题讨论】:

  • 你试过使用同步块吗?
  • @JoseLuis 这是一个分布式系统,锁需要在数据库中。

标签: java mysql spring


【解决方案1】:

我最终使用了"SELECT ... FOR UPDATE" 查询。执行此查询后,所有其他读取/写入都将被锁定,直到当前事务提交或回滚。还需要用@Transactional注释方法。但是这里的行锁和事务是两个不同的问题。测试结果令人满意。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-05-01
    • 2018-08-03
    • 2015-06-08
    • 1970-01-01
    • 1970-01-01
    • 2012-06-03
    • 1970-01-01
    • 2019-03-16
    相关资源
    最近更新 更多