Вопрос

У меня есть приложение для управления продажами, запасами и оплатой на оптовом складе через веб-интерфейс.В частности, при выполнении заказа необходимо создать строку, соответствующую каждому заказанному продукту в соответствующем количестве.Проверка наличия на складе осуществляется в момент заказа.

Учитывая следующие два способа проверки заказа:

  1. Используйте триггер BEFORE INSERT на столе OrderLine, это выполняет SELECT на Product проверка наличия достаточного запаса.

  2. Сделайте SELECT ... FROM OrderLine JOIN Product WHERE quant < stock.

Мой вопрос:Какая из этих двух альтернатив предпочтительнее и почему/для какого сценария?

Это было полезно?

Решение

Я вижу, что вы делаете только выбор в обоих вариантах. Если вы хотите убедиться, что вы не продаете больше, чем в магазине (Stock), вы должны уменьшить свою акцию в той же сделке, которую вы размещаете. В Postgresql 9.1 Вы можете использовать Модификация данных CTE для работы:

WITH u AS (
   UPDATE product SET quant = quant - <put_order_quant_here>
   WHERE  product_id = <order_prod_id>
   AND    quant >= <put_order_quant_here>
   RETURNING product_id, <put_order_quant_here> AS quant
   )
INSERT INTO order_detail (order_id, product_id, quant)
SELECT <put_order_id_here>, product_id, quant
FROM   u;

Обновление в CTE возвращает значения только в том случае, если продукт имеет достаточное количество запасов. В этом случае количество уменьшается в той же транзакции, непосредственно перед размещением порядка.

Поместите все получения порядка в одну транзакцию, если какая-либо из них не встает, ROLLBACK.


Возможные тупики

Еще один совет: этот сценарий может легко привести к тупикам. Скажем, у вас есть два заказа одновременно, оба хотят, чтобы продукт A и B. Первый заказ начинается с размещения Order_detail на A, второй начинается с B. Затем две транзакции блокируют друг друга. Каждый из них будет ждать, пока другой завершит. А тупик следит за.

В PostgreSQL транзакция будет ждать некоторое время, когда она застопорится замками. В зависимости от вашей настройки deadlock_timeout (По умолчанию - 1 с, что я установил, по крайней мере, на 5 с на невозможных производственных серверах), будет выполнена проверка на возможное состояние тупика.

После обнаружения одна транзакция будет прервана и сообщит о исключении тупика. Другой может закончить. Который трудно предсказать.

Есть простой способ избежать такого рода тупиков: всегда помещайте свой order_details в Последовательный порядок. Анкет Как продукты, заказанные product_id. Анкет Таким образом, приведенный выше сценарий никогда не может произойти.

Другие советы

Обновлять:

Я написал этот пост до того, как был добавлен тег postgresql, но концепции должны быть схожими.По сути, вам нужно иметь возможность каким-либо образом заблокировать запись, чтобы гарантировать, что выбранная вами стоимость акций останется той же стоимостью, которую вы уменьшили.Та же транзакция, которая блокирует запись, должна обновить запас и вставить его в таблицу OrderLine.Как только вы определите, что запасов нет в наличии, отмените всю транзакцию.

Если эта обработка выполняется в пакетной операции одним процессом, вам не нужно беспокоиться о блокировке отдельных записей, но вы должны убедиться, что одновременно может выполняться только один пакетный процесс.


Посмотрите...

  1. А ЖДАТЬ предложение оператора SELECT.
  2. А ОПТОВЫЙ СБОР предложение оператора SELECT.
  3. А ДЛЯ ВСЕХ заявление.

Вы, вероятно, также захотите убедиться, что во всех записях имеется достаточный запас, поэтому вы можете захотеть агрегировать некоторые из них независимо от того, доступны ли запасы или нет.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с dba.stackexchange
scroll top