Frage

Ich habe eine Managementanwendung von Verkäufen, Aktien und Zahlungen in einem Lagerhause für den ganzen Saler von einer Weboberfläche. Insbesondere muss eine Reihenfolge eine Linie erstellen, die jedem mit der jeweiligen Menge bestellten Produkt entspricht. Die Validierung der Aktienverfügbarkeit erfolgt zum Zeitpunkt der Bestellung.

Berücksichtigung der folgenden zwei Validierungsweisen auf der Reihenfolge:

  1. Verwenden Sie einen Auslöser BEFORE INSERT auf den Tisch OrderLine, das macht eine ausgewählte auf Product Überprüfen Sie, ob es genügend Bestand gibt.

  2. Mach a SELECT ... FROM OrderLine JOIN Product WHERE quant < stock.

Meine Frage ist: Welche dieser beiden Alternativen ist vorzuziehen und warum / für welches Szenario?

War es hilfreich?

Lösung

Ich sehe nur, dass Sie in beiden Varianten eine Auswahl machen. Wenn Sie sicherstellen möchten, dass Sie nicht mehr verkaufen als Sie auf Lager haben (Aktien), müssen Sie Ihre Aktien in derselben Transaktion verringern, die Sie die Bestellung aufgeben. Im PostgreSQL 9.1 Sie könnten a verwenden datenmodifizierender CTE für die Arbeit:

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;

Das Update im CTE gibt nur Werte zurück, wenn das Produkt ausreichend Aktien hat. In diesem Fall wird die Menge in derselben Transaktion reduziert, kurz vor der Bestellung.

Stellen Sie alle Bestelldetails in eine Transaktion ein, wenn einer von ihnen nicht einfügt, ROLLBACK.


Mögliche Deadlocks

Ein weiterer Ratschlag: Dieses Szenario könnte leicht zu Deadlocks führen. Angenommen, Sie haben zwei Bestellungen, die gleichzeitig eingehen, beide möchten Produkt A und B. Die erste Bestellung beginnt damit, den Order_detail auf a zu platzieren. Die zweite beginnt mit B. dann blockieren sich die beiden Transaktionen gegenseitig. Jeder von ihnen wartete darauf, dass der andere abgeschlossen ist. EIN Sackgasse folgt.

In PostgreSQL wartet eine Transaktion einige Zeit, wenn sie von Schlössern ins Stocken geraten. Abhängig von Ihrer Einstellung von deadlock_timeout (Standard ist 1s, das ich auf mindestens 5s auf nicht verblüfften Produktionsservern festgelegt habe.

Nach der Erkennung wird eine Transaktion abgebrochen und melden eine Deadlock -Ausnahme. Der andere kann fertig werden. Welches ist schwer vorherzusagen.

Es gibt eine einfache Möglichkeit, diese Art von Deadlocks zu vermeiden: Immer Ihre platzieren order_details in einem konsequente Ordnung. Wie Produkte bestellt von product_id. Auf diese Weise kann das obige Szenario niemals passieren.

Andere Tipps

Aktualisieren:

Ich habe diesen Beitrag erstellt, bevor das PostgreSQL -Tag hinzugefügt wurde, aber die Konzepte sollten ähnlich sein. Grundsätzlich müssen Sie in der Lage sein, den Datensatz in irgendeiner Weise zu sperren, um sicherzustellen, dass der von Ihnen ausgewählte Aktienwert den von Ihnen gesenkten Aktienwert bleibt. Die gleiche Transaktion, die den Datensatz sperrt, sollte die Aktie aktualisieren und in die Bestelllinie einfügen. Sobald Sie feststellen, dass Aktien nicht verfügbar sind, rollen Sie die gesamte Transaktion zurück.

Wenn diese Verarbeitung in einem Stapelbetrieb nach einem Vorgang durchgeführt wird, müssen Sie sich nicht mit der Verriegelung einzelner Datensätze befassen. Sie sollten jedoch sicherstellen, dass nur ein Stapelprozess gleichzeitig ausgeführt werden kann.


Einblick in...

  1. Das WARTEN Klausel der Auswahlanweisung.
  2. Das Massensammlung Klausel der Auswahlanweisung.
  3. Das FÜR ALLE Aussage.

Sie möchten wahrscheinlich auch sicherstellen, dass alle Einträge genügend Aktien haben. Möglicherweise möchten Sie, ob einige der Aktie verfügbar sind oder nicht.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit dba.stackexchange
scroll top