我们有一个对MySql有读写的方法,这个方法可以被多线程调用。数据库操作如下:
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锁等额外的组件来做。我想知道如何在 Spring 中执行此操作?
最佳答案
I 最终使用了 "SELECT ... FOR UPDATE"
查询。执行此查询后,所有其他读/写都将被锁定,直到当前事务提交或回滚。还需要用@Transactional
注解方法。但是这里的行锁和事务是2个不同的关注点。测试结果令人满意。
关于java - 在 Spring 中使用事务进行同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55626970/