java - 如何在 Oracle 上重复此操作?(选择更新 + order by + LIMIT 1 + 跳过锁定)
问题描述
我有控制器:
@GetMapping("/old")
public Product getOld() {
Product omeOld = productService.getOneOld();
log.info(String.valueOf(omeOld.getId()));
return omeOld;
}
服务:
@Override
@Transactional
public Product getOneOld() {
Product aNew = productsRepository.findTop1ByStatusOrderByCountAsc("NEW");
try {
Thread.sleep(5000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
return aNew;
}
和存储库:
@Repository
public interface ProductsRepository extends JpaRepository<Product, Long> {
Product findTop1ByStatusOrderByCountAsc(String status);
}
我启动 JMeter 并在 5 个线程中发送 5 个请求。结果我在 5 秒后得到 5 个响应。每个请求都按秒处理。但在日志中我看到下一个:
2018-09-14 14:04:35.524 INFO 9048 --- [nio-8080-exec-1] c.e.l.demo.controller.ProductController : 1
2018-09-14 14:04:35.525 INFO 9048 --- [nio-8080-exec-2] c.e.l.demo.controller.ProductController : 1
2018-09-14 14:04:35.532 INFO 9048 --- [nio-8080-exec-3] c.e.l.demo.controller.ProductController : 1
2018-09-14 14:04:35.534 INFO 9048 --- [nio-8080-exec-4] c.e.l.demo.controller.ProductController : 1
2018-09-14 14:04:35.534 INFO 9048 --- [nio-8080-exec-6] c.e.l.demo.controller.ProductController : 1
每个线程选择同一行并处理它。我需要第一个线程选择第一行,第二个线程选择第二行等等。我尝试使用@Lock(LockModeType.PESSIMISTIC_WRITE)
:
@Lock(LockModeType.PESSIMISTIC_WRITE)
Product findTop1ByStatusOrderByCountAsc(String status);
现在,当我开始时,JMeter
我有下一个行为:
第一个线程工作 5 秒,之后第二个线程工作 5 秒,依此类推。 25 秒所有 5 个线程。并在日志中:
2018-09-14 14:11:40.564 INFO 13724 --- [nio-8080-exec-5] c.e.l.demo.controller.ProductController : 1
2018-09-14 14:11:45.566 INFO 13724 --- [nio-8080-exec-4] c.e.l.demo.controller.ProductController : 1
2018-09-14 14:11:50.567 INFO 13724 --- [nio-8080-exec-2] c.e.l.demo.controller.ProductController : 1
2018-09-14 14:11:55.568 INFO 13724 --- [nio-8080-exec-1] c.e.l.demo.controller.ProductController : 1
2018-09-14 14:12:00.570 INFO 13724 --- [nio-8080-exec-3] c.e.l.demo.controller.ProductController : 1
所有线程都选择同一行(如果我在第一个线程中更改此 roe - 如果条件不匹配,它将不会在第二个线程中选择)。
我试试这个:
@Query(value = "Select * from products where status = ?1 order by count asc LIMIT 1 for update", nativeQuery = true)
Product findTop1ByStatusOrderByCountAsc(String status);
结果是一样的。
但我需要 - 第一个线程选择第一行并阻止它/第二个线程选择下一个未阻止的行并处理。我接下来尝试:
@Query(value = "Select * from products where status = ?1 order by count asc LIMIT 1 for update of products skip locked", nativeQuery = true)
Product findTop1ByStatusOrderByCountAsc(String status);
它工作正常!:
2018-09-14 14:25:00.355 INFO 7904 --- [io-8080-exec-10] c.e.l.demo.controller.ProductController : 4
2018-09-14 14:25:00.355 INFO 7904 --- [nio-8080-exec-4] c.e.l.demo.controller.ProductController : 3
2018-09-14 14:25:00.355 INFO 7904 --- [nio-8080-exec-9] c.e.l.demo.controller.ProductController : 1
2018-09-14 14:25:00.358 INFO 7904 --- [nio-8080-exec-5] c.e.l.demo.controller.ProductController : 5
2018-09-14 14:25:00.359 INFO 7904 --- [nio-8080-exec-2] c.e.l.demo.controller.ProductController : 6
每个线程中的每个选择都从非阻塞行中选择一行!
但是我怎么能用 Oracle 重复这个呢?在 oracle 中我不能写LIMIT 1
,如果我使用ROWNUM = 1
每个线程总是选择同一行。
解决方案
推荐阅读
- xamarin.forms - 从 Xamarin.forms.ImageSource 到 UIKit.ImageView 的转换
- vlcj - vlcj 在流式传输时冻结在本地
- sed - 删除破折号 (-) 和第一个点 (.) 之间的字符串
- angular - 通过按钮更改离子警报 CssClass
- c# - 使用 C# 从 Json 中提取完整数据
- google-identity - Google YOLO 停止工作:不允许客户端源使用此 API
- javascript - textContent 和 innerHTML 不会改变 DOM
- c# - .Net Blazor 优于 Angular、React 或其他 JavaScript 框架
- css - CSS:为什么绝对div内的图像底部有一个小间隙?
- excel - “应用程序”对象是否有更多方法?