php doctrine concurrency pessimistic_write is not preventing additional requests from getting old data

huangapple go评论76阅读模式
英文:

php doctrine concurrency pessimistic_write is not preventing additional requests from getting old data

问题

I can provide a translation of the code portion you provided:

php: 8.1
doctrine: 2.9.2

我在实现Doctrine并发性时遇到问题。我查看了文档和一些问题,但找不到问题所在。

我的应用程序跟踪库存。多个请求可能同时更新库存。我添加了一个sleep来测试。第二个请求等待第一个请求完成,所以锁似乎部分起作用。但是,第二个请求使用起始库存而不是第一个请求的调整后库存。

- 库存:50
- 第一个请求:50+5 = 55
- 第二个请求:50+5 = 55(应该是55+5 = 60

以下是持久性代码:

$this->em->beginTransaction();
try{
    $inventoryID = $stockAdjustment->getInventory()->getId();
    $this->detach($stockAdjustment->getInventory());
    $inventory = $this->inventoryRepo->find($inventoryID, LockMode::PESSIMISTIC_WRITE);
    $this->refresh($inventory);
    sleep(15);
    $stockAdjustment->setInventory($inventory);
    $stockAdjustment->setPreAdjustmentStock($inventory->getStock());
    $inventory->modifyStock($stockAdjustment->getQuantity());

    $this->em->persist($inventory);
    $this->em->persist($stockAdjustment);
    $this->em->flush();
    $this->em->commit();
}
catch (\Throwable $e){
    $this->em->rollback();
    throw $e;
}

I hope this helps with your translation needs.

英文:

php: 8.1
doctrine: 2.9.2

I am having a problem implementing concurrency in doctrine. I've looked through the documentation and a few questions and I cannot see what my issue is.

My app is tracking inventory. There is a chance that multiple requests may update the stock at the same time. I put in a sleep to test. The 2nd request waits for the 1st request to finish, so the lock appears to be partially working. However, the 2nd request uses the starting stock instead of the adjusted stock of the 1st request.

  • Stock: 50
  • 1st request: 50+5 = 55
  • 2nd request: 50+5 = 55 (should be 55+5 = 60)

Here is the persistence code:

$this->em->beginTransaction();
    try{
        $inventoryID = $stockAdjustment->getInventory()->getId();
        $this->detach($stockAdjustment->getInventory());
        $inventory = $this->inventoryRepo->find($inventoryID, LockMode::PESSIMISTIC_WRITE);
        $this->refresh($inventory);
        sleep(15);
        $stockAdjustment->setInventory($inventory);
        $stockAdjustment->setPreAdjustmentStock($inventory->getStock());
        $inventory->modifyStock($stockAdjustment->getQuantity());

        $this->em->persist($inventory);
        $this->em->persist($stockAdjustment);
        $this->em->flush();
        $this->em->commit();
    }
    catch (\Throwable $e){
        $this->em->rollback();
        throw $e;
    }

Before this occurs, the inventory is found when hydrating the adjustment. I left in the detach and refresh lines to show that I've tried that. Normally, Inventory is mapped to InventoryAdjustment with cascade persist. In this case, I've removed the cascade persist and am saving the inventory directly.

答案1

得分: 0

这是要翻译的内容:

It was a stupid mistake that I realized just after posting. Stock can be a couple different types depending on the type of inventory, so stock is not actually stored on the Inventory object. I have another class InventoryStock and putting the lock on that resolved the issue. InventoryStock has a discriminator map for a few sub classes, but putting the lock on InventoryStock worked.

英文:

It was a stupid mistake that I realized just after posting. Stock can be a couple different types depending on the type of inventory, so stock is not actually stored on the Inventory object. I have another class InventoryStock and putting the lock on that resolved the issue. InventoryStock has a discriminator map for a few sub classes, but putting the lock on InventoryStock worked.

huangapple
  • 本文由 发表于 2023年6月26日 20:46:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/76556829.html
  • concurrency
  • doctrine
  • doctrine-orm
  • php

如何将MySQL表列作为变量放入 :?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定