并行事务中的冻结插入

jvlzgdj9  于 2021-06-15  发布在  Mysql
关注(0)|答案(0)|浏览(232)

我有两个可共享倒计时闩锁事务。每个事务在单独的线程中执行。我需要这样的机制来重现“脏读”的情况。第一个事务更新“目标实体”并刷新更改而不提交,然后我将线程设置为等待状态(countdownlatch)。
在第二个事务中,我获取“目标实体”并将脏字段复制到另一个实体并保存。保存操作之后,我倒计时以继续第一个事务并回滚它。
下面是事务处理方法的代码示例。第一个:

@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");

}

第二个:我有一个由事务和 Package 器服务绑定的主服务来倒计时闩锁。
Package 器:

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(订单);
线被冻住了。我在日志中只看到insert语句。
但如果我去掉“订单”和“产品”之间的关系,插入内容就不会冻结。我猜在“积”和倒计时锁上有死锁。但是这个问题只发生在mysql jdbc中。如果我切换到postgresjdbc,那就没有问题了。
ps:第一个事务执行以下查询:

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

第二个执行:

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

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题