Rolf B: mysql Insert Row if not exists

Beitrag lesen

Hallo Mitleser,

stimmt wohl, race conditions rufen nach Transaktionen. Man muss nur aufpassen, dass man dann die race condition nicht gegen einen Deadlock eintauscht. Oder gegen einen Flaschenhals.

Und die Frage, warum es beim Generieren einer Rechnungsnummer überhaupt zu Duplikaten kommen kann, ruft die Folgefrage auf: Warum keine AUTO INCREMENT Rechnungsnummer? Aber das ist vermutlich die alte Seuche, die aus manuell geführten Verwaltungen kommt: Solche Nummern müssen sprechend sein und mindestens mal mit der Jahreszahl anfangen, z.B. 210017. Natürlich ohne Jahrhundert, um der Enkelgeneration ein weiteres Y2100[1]-Problem zu vererben. Und mit zu wenig Stellen (10000 Rechnungen im Jahr? Hamma nich, höchstens 1000 oder so). Und wenn so ein Prozess erstmal da ist, wird man ihn nur noch los, wenn man die Bude abbrennt und neu gründet.

  • es sollte eine DB-Engine sein, die Row Locks kennt (bei MySQL/Maria: InnoDB, MyISAM kennt nur Table Locks)
  • die Sätze, die auf die Erstellung der Rechnungsnummer Einfluss haben, sollten mit SELECT ... FOR UPDATE gelesen werden, so dass Folge-SELECTs von anderen Connections warten müssen. Wenn gar nichts anderes geht, macht man für solche Zwecke eine separate Semaphoren-Tabelle, die man mit table lock reserviert oder in der man einzelne Sätze per row lock sperrt, die für den jeweiligen zu serialisierenden Ablauf vorgesehen sind.
  • Es sollte nach aller Möglichkeit nur ein einziger Satz FOR UPDATE gelockt werden, denn ein zweiter Lock immer zu einem Deadlock führen wenn ein anderer Client die gleichen Objekte in anderer Reihenfolge locken will
  • Die Transaktion sollte ausschließlich das Erstellen und Speichern der Rechnungsnummer umfassen, nach sollten die Locks erstmal wieder freigegeben werden, um die DB nicht zu lange zu blockieren.

Rolf

--
sumpsi - posui - obstruxi

  1. Nach "Y2K" die übernächste Goldmine für Sanierungsprogrammierer. Sprechende Nummernkreise ohne Jahrhundert laufen über, und der 29.02.2100 wird auch spannend. Vorher ist noch "Y2K38" dran - der time_t Überlauf 2038. Aber die Kisten, die dafür empfänglich sind, versagen vermutlich schon 2036, wenn NTP überläuft, weil sie zum veralteten time_t garantiert auch einen veralteten NTP-RfC implementieren. ↩︎