Question

J'ai une application de gestion des ventes, des stocks et le paiement sur l'ensemble de l'entrepôt à partir d'une interface Saler Web. En particulier, quand une commande est effectuated il doit créer une ligne correspondant à chaque produit commandé avec la quantité respective. La validation de la disponibilité des stocks se fait au moment de l'ordre.

Compte tenu des deux modes de validation ordre suivant:

  1. Utilisez un BEFORE INSERT de déclenchement sur la table OrderLine, qui fait un SELECT sur Product vérifier il y a assez de stock.

  2. Faites un SELECT ... FROM OrderLine JOIN Product WHERE quant < stock.

Ma question est: Laquelle de ces deux alternatives est préférable, et pourquoi / pour ce scénario

?
Était-ce utile?

La solution

Je vois que vous faites un SELECT dans les deux variantes. Si vous voulez vous assurer que vous ne vendez pas plus que ce que vous avez en magasin (stock), vous devez réduire votre stock dans la même transaction que vous passez la commande. PostgreSQL 9.1 vous pouvez utiliser un données de modification de CTE pour le travail:

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;

L'instruction UPDATE dans le CTE ne retourne que des valeurs si le produit a un stock suffisant. Dans ce cas, la quantité est réduite dans la même transaction, juste avant la commande.

Mettez tous les détails d'ordre-en une seule transaction, si aucun d'entre eux ne parvient pas à INSERT, ROLLBACK.


possible des interblocages

Un autre conseil: ce scénario pourrait facilement conduire à des impasses. Dites, vous avez deux commandes à venir en même temps, les deux veulent des produits A et B. La première commence d'ordre en plaçant le order_detail sur A, le second commence par B. Ensuite, les deux opérations bloquer les uns les autres. Chacun d'entre eux attendraient l'autre pour terminer. Un impasse Ensues.

Dans PostgreSQL une transaction attendra pendant un certain temps quand il est bloqué par des verrous. En fonction de vos paramètres de deadlock_timeout (valeur par défaut est de 1 s, que je définis sur au moins 5 s sur des serveurs de production sans trouble), vérifie une condition de blocage possible sera réalisée.

Une fois détecté, une transaction sera annulée et signaler une exception impasse. L'autre peut finir. Lequel est difficile à prévoir.

Il y a une façon simple d'éviter ce genre de blocages: placez toujours votre order_details dans un ordre cohérent . Comme les produits commandés par product_id. De cette façon, le scénario ci-dessus ne peut jamais se produire.

Autres conseils

Mise à jour:

J'ai fait ce poste avant la balise postgresql a été ajouté, mais les concepts devrait être similaire. Fondamentalement, vous devez être en mesure de verrouiller l'enregistrement de quelque façon à faire en sorte que la valeur du stock sélectionnée reste la valeur du stock vous diminuez. La même transaction qui bloque le dossier doit mettre à jour le stock et l'insérer dans la table OrderLine. Dès que vous déterminez que le stock est pas disponible rouler tout le dos de la transaction.

Si ce traitement est effectué dans une opération discontinue par un processus, alors vous n'avez pas besoin de se préoccuper de verrouillage des dossiers individuels, mais vous devez vous assurer que seul un processus de traitement par lots peut être en cours d'exécution en même temps.


Rechercher dans ...

  1. clause WAIT de la
  2. COLLECT clause du instruction SELECT.
  3. La déclaration FORALL .

Vous auriez sans doute aussi vouloir faire en sorte que toutes les entrées avaient assez de stock, vous voudrez peut-être un peu à agrégats si le stock est disponible ou non.

Licencié sous: CC-BY-SA avec attribution
Non affilié à dba.stackexchange
scroll top