Замороженная вставка в параллельной транзакции - PullRequest
0 голосов
/ 05 января 2019

У меня есть две транзакции с общим делом обратного отсчета. Каждая транзакция выполняется в отдельном потоке. Мне нужен такой механизм, чтобы воспроизвести ситуацию «грязного чтения». Первая транзакция выполняет обновление «целевой сущности» и сбрасывает изменения без фиксации, затем я устанавливаю поток в состояние ожидания (countDownLatch).

Во второй транзакции я выбираю "целевой объект", копирую грязное поле в другой объект и сохраняю. После операции сохранения я делаю countDown, чтобы продолжить первую транзакцию и выполнить откат.

Ниже приведены примеры кода методов транзакции. Первый:

@Transactional
public void updatePrice() {
    log.info("Start price updating. Thread '{}'", Thread.currentThread().getName());
    Collection<Product> products = productRepository.findAll();
    products.forEach(this::updatePrice);
    productRepository.saveAll(products);
    entityManager.flush();
    log.info("Flash changes and wait for order transaction");
    try {
        latch.await();
    } catch (InterruptedException e) {
        log.error("Something wrong");
        Thread.currentThread().interrupt();
    }
    log.error("Rollback changes");
    throw new RuntimeException("Unexpected exception");

}

Второй: у меня есть основной сервис, который ограничен транзакцией и сервисом-оберткой для отсчета защелки.

Wrapper:

public void doOrder(Long productId, Long amount) {
    log.info("Start do order. Thread '{}'", Thread.currentThread().getName());
    orderService.doOrder(productId, amount);
    log.info("Order transaction committed");
    latch.countDown();
    log.info("Finish order process");
}

Основной сервис:

@Transactional
public void doOrder(Long productId, Long amount) {
    Product product = productRepository.findById(productId).get();
    log.info("Get product");
    Order order = Order.builder().price(product.getPrice()).amount(amount).productId(new Long(productId)).build();
    orderRepository.save(order);
    log.info("Save order");
}

Итак, на линии

orderRepository.save (заказ);

нить замерзла. Я вижу только оператор вставки в журналах.

Но если я удалю связь между 'order' и 'product', вставка не замерзнет. Я предполагаю, что есть «тупик» на «product» и countDownLatch. Но эта проблема возникает только с MySQL JDBC. Если я переключаюсь на Postgres JDBC, то нет проблем там.

PS: Первая транзакция выполняет следующие запросы:

select * from product;
update product set price = ...

Второй выполняет:

select * from product where id = ...;
insert into product_order(product_id, amount, price) values (...)   
...