#spring #hibernate #spring-data-jpa
Вопрос:
у меня проблема : у меня есть объект продукта, у которого есть 2 столбца id и количество _ так что у меня есть 2 api
- один для обновления это приведет к обновлению количества сущности продукта (количество = количество — 1)
- один для обновления это обновит количество сущности продукта (количество = количество 1) проблема в том, что я вызываю 2 api одновременно, этот результат не мой ожидаемый вот моя диаграмма введите описание изображения здесь
кто-нибудь может помочь мне поблагодарить вас
Комментарии:
1. Вы вызываете оба Api одновременно ?? вы пробовали использовать пессимистическую блокировку(Pessimistic_write_lock) в spring jpa ?
2. что ж, я изучу это, спасибо за ваш ответ
Ответ №1:
Ну, для вашего конкретного сценария существует концепция, называемая блокировкой. И существует два типа блокировки
- Оптимистичный
- Пессимистический
Идея заключается в том, что когда одна транзакция обновляет строку таблицы БД, вы не должны позволять другой транзакции обновлять эту строку до тех пор, пока не будет зафиксирована предыдущая.
В приложении существует несколько способов достижения такого типа блокировки. Мы можем описать этот параллельный процесс обновления как столкновение. В системе, где столкновение происходит не очень часто, вы можете использовать подход с оптимизацией блокировки.
При оптимистическом подходе вы сохраняете version
номер в своем ряду. Когда вы выполняете обновление, вы увеличиваете версию на 1. Давайте проанализируем ваш сценарий сейчас и вызовем две ваши службы I (увеличение) и D (уменьшение). У вас есть строка продукта P в таблице базы данных, где quantity = 3
, version = 0
. Когда I
и D
вызывается для них обоих, когда они извлекаются P
из базы данных, состояние P
выглядит следующим образом
количество = 3, версия = 0
Теперь D
выполняется первым, уменьшите и сохраните P
ваш запрос на обновление, как показано ниже
UPDATE Product p set p.quantity = :newQuantity
, p.version = p.version 1 where p.version = :oldVersion and p.id = :id
Для случая D
значения newQuantity = 2
(oldQty - 1)
и значения oldVersion = 0
(мы выбрали его в начале)
Теперь текущее состояние P
выглядит следующим образом
количество = 2, версия = 1
Теперь при I
попытке выполнить вы должны сгенерировать тот же запрос на обновление, но для этого случая значение newQuantity = 4
(oldQty 1)
и значение oldVersion = 0
(мы получили его в начале).
Если вы добавите эти значения в запрос на обновление, ваша строка не будет обновлена, так как часть проверки версии будет ложной. После этого вы можете создать любое исключение блокировки, чтобы уведомить своего клиента о том, что запрос не может быть завершен, и можете повторить попытку. Это в основном основная концепция оптимистичной блокировки, и есть гораздо более эффективные способы справиться с ней с помощью таких фреймворков, как Hibernate
Здесь вы можете заметить, что мы не отклоняли ни один из запросов на чтение во время обновления строки, но при Pessimistic
блокировке вы отказываете в любом запросе на чтение, когда выполняется другая транзакция. Таким образом, в основном, когда D
происходит процесс уменьшения I
, вы не сможете прочитать значение, и оттуда вы можете вернуться к своему клиенту, сказав, что запрос не был завершен. Но этот подход требует затрат на чтение тяжелых таблиц в обмен на жесткую целостность данных.
Комментарии:
1. большое вам спасибо, сэр