【发布时间】:2021-04-09 14:25:37
【问题描述】:
我有一张表,其中的值是这样的,
| id | value | status |
|---|---|---|
| 1 | a | PENDING |
| 2 | b | COMPLETE |
| 3 | c | INPROGRESS |
| 4 | d | PENDING |
| 5 | e | PENDING |
现在,我有两个线程正在尝试做同样的事情。它们如下。
- 从表中获取一条不是 INPROGRESS 或 COMPLETE 的记录。
- 将其标记为 INPROGRESS。
- 处理记录。
- 将其标记为 COMPLETE。
我已经实现了以下内容,以确保两个线程不会同时拾取相同的记录。
- “select * from table where status not in ('COMPLETE', 'INPROGRESS') limit 1 for update”从表中获取合适的记录。
- 在单个事务中完成第 1 步和第 2 步,以便表变为读锁定状态,直到拾取的记录被标记为 INPROGRESS。
但是,我面临以下问题
如果线程 1 正在获取记录,而它尚未将记录标记为“INPROGRESS”,则另一个线程(线程 2)尝试执行相同操作。线程 2 有时会首先获取线程 1 已经选择的记录,并在线程 1 事务解除锁定后返回状态为“INPROGRESS”的相同记录。
除了在获取记录后添加状态值检查外,我无法弄清楚如何解决此问题,但我认为可能有更好的方法。
如果有更好的方法,请告诉我。
这是负责获取要处理的记录的方法的示例代码,
// 存储库
class TableRepository implements JpaRepository<Table, Long> {
@Query(value = "select * from table where status not in ('COMPLETE', 'INPROGRESS') limit 1 for update", nativeQuery=true)
Table getOneValidRecord();
}
// 服务类
class TableService {
@Autowired
private TableRepository repository;
@Transactional(propagation = Propagation.REQUIRES_NEW)
public Table getOneValidRecord() {
Table table = repository.getOneValidRecord();
table.setStatus("INPROGRESS");
return repository.save(table);
}
}
【问题讨论】:
标签: mysql multithreading spring-boot spring-data-jpa