【发布时间】:2021-12-15 15:27:40
【问题描述】:
我有一个要求,请求必须获得对数据库中最顶层行的访问权限,读取并删除它,通过锁定特定行一次性完成。
这里的用例是 URL 缩短应用程序将查询此表以获取预先生成的 URL 密钥并在完成后将其删除。
我使用的是Spring Data JPA,所以我将添加以下代码
URLKeyEntity.java
@Entity(name = "urlKeyEntity")
@Table(name = "url_key")
@Data
public class URLKeyEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String urlKey;
}
URLKeyRepository.java
@Repository
public interface URLKeyRepository extends JpaRepository<URLKeyEntity, Long> {
@Lock(LockMode.PESSIMISTIC_WRITE)
@Query("SELECT u FROM urlKeyEntity u ORDER BY u.id")
List<URLKeyEntity> fetchTopRow(Pageable p);
}
URLKeyService.java
@Service
public class URLKeyService {
@Autowired
private URLKeyRepository urlKeyRepository;
@Transactional
public String getUrlKey() {
final URLKeyEntity u = urlKeyRepository.findTopRow(PageRequest.of(0,1));
final String key = u.get(0).getUrlKey();
urlKeyRepository.delete(u.getId());
}
}
我难以理解的是,当多个线程试图执行相同的方法时,这将如何发挥作用。
比如说,线程 T1 和 T2 正在执行相同的方法并行。在任何给定时间点,T1 都会获取第一行 R1 上的锁,而 T2 则等待同一行上的锁。
到 T1 完成时,行本身并不存在,那么 T2 将如何进行?
如果我们在整个表上获取锁,那么随着写入负载的增加,这可能会导致性能下降。
处理此问题的最佳方法是什么,以免锁定成为可伸缩性的瓶颈?
【问题讨论】:
标签: java mysql spring multithreading spring-data-jpa