как повторить это на Oracle?(Выберите для обновления + заказ по + LIMIT 1 + пропуск заблокирован) - PullRequest
0 голосов
/ 14 сентября 2018

У меня есть контроллер:

@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

Все потоки выбирают одну и ту же строку (если я изменю эту косулю в первом потоке - он не будет выбран во втором потоке, если условия не совпадают).

Я пытаюсь это:

@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?В оракуле я не могу написать LIMIT 1, и если я использую ROWNUM = 1, каждый поток всегда выбирает одну и ту же строку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...