Schrift
[thread]10140[/thread]

Script wird doppelt ausgeführt?!



<< >> 9 Einträge, 1 Seite
Gast Gast
 2007-08-20 12:02
#98405 #98405
Hallo,

ich habe ein Problem, das ich mir wirklich nicht erklären kann. Hier ist der generelle Ablauf des Scripts:

- Rechnungsnummer einlesen
- Einige Operationen abarbeiten
- Rechnung verschicken
- Rechnungsnummer erhöhen
- Weitere Operationen abarbeiten

Dabei ist es so, das ein Kunde halt anfangs eine Rechnungsnummer zugeordnet bekommt. Ein anderer Kunde bekommt auf Grund der späteren Erhöhung generell immer eine andere Nummer.

Bei 1-2% der Fälle bekommt aber der gleiche Kunde 2 Rechnungen mit der selben Rechnungsnummer.

Jetzt meine Fragen:
1) Wie kann das sein? Wird das Script durch eine W-LAN Unterbrechung o.ä. ein zweites Mal innerhalb von ein paar hundertstel Sekunden ausgeführt, so das sich Einlesen und Erhöhen der Rechnungsnummer überschneiden?
2) Wie kann man das Problem lösen? Die Rechnungsnummer wird über eine MYSQL Datenbank verwaltet.

Vielen Dank im Voraus.
pq
 2007-08-20 13:04
#98406 #98406
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
das erhöhen der rechnungsnummer muss auf jeden fall atomar passieren.
du sagst leider nichts darüber, wie du die nummer erhöhst, ob du transaktionen
benutzt oder nicht etc.
szenario: prozess P1 liest rechungsnummer 123. prozess P2 liest rechnungsnummer 123.
P1 verschickt rechnung und schreibt 124 in die datenbank. P2 verschickt rechnung
und schreibt auch 124 in die datenbank.

lösung: wenn keine anderen daten davon abghängig sind, erhöhe die nummer folgendermassen:
[sql]UPDATE foo set rechnungsnummer = rechnungsnummer + 1 where ...[/sql]
das ist eine atomare operation.
ansonsten musst du InnoDB benutzen und transaktionen.
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem
Gast Gast
 2007-08-20 13:38
#98409 #98409
Hi,

erstmal Danke für deine Antwort. Das Problem dabei ist, das ich zuerst die Rechnungsnummer benötige, da damit ein externes Zahlungssystem angesteuert wird. Wenn die Zahlung dann fehlschlägt darf die Nummer aber nicht erhöht werden.

Das Problem mit den Nummern ist aber weniger tragisch.

Das Problem ist halt, das bei einem Kunden die Zahlung zweimal angestoßen wird, was natürlich nicht wirklich toll ist. Hier noch einmal der Ablauf aus einer etwas anderen Sicht:

1. Prüfe, ob der Kunde bereits eine Zahlung durchgeführt hat (in MYSQL DB)
2. Führe externes Zahlungssystem aus
3. Schreibe in die Datenbank, das die Zahlung durchgeführt worden ist
(Die Zahlung soll nur beim ersten Mal durchgeführt werden. Danach kann er den Service ein weiteres Mal kostenlos in Anspruch nehmen)

Und hierbei werden bei einem Kunden halt manchmal 2 Zahlungen direkt hintereinander ausgeführt.

Hatte vergessen das das ein CGI/Perl Script ist, das über den Browser ausgeführt wird.

Für mich stellt sich jetzt halt erstmal die Frage, wie es sein kann, das das Script 2mal direkt hintereinander von einem Kunden ausgeführt wird, so das sich die Schritte 1-3 überschneiden.
MisterL
 2007-08-20 14:28
#98410 #98410
User since
2006-07-05
334 Artikel
BenutzerIn
[default_avatar]
Welche Version der MySQL DB liegt vor ? Ich rate mal, dass dort der Bug zu finden ist...
“Perl is the only language that looks the same before and after RSA encryption.”
pq
 2007-08-20 14:32
#98411 #98411
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
Gast+2007-08-20 11:38:25--
Das Problem mit den Nummern ist aber weniger tragisch.

hmm, wenn du meinst...
wenn aber der erste kunde ankommt und eine rechnungsnummer hat, die auch ein anderer
kunde hat, dann beschwer dich nicht.
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem
pq
 2007-08-20 14:35
#98412 #98412
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
Gast+2007-08-20 11:38:25--
1. Prüfe, ob der Kunde bereits eine Zahlung durchgeführt hat (in MYSQL DB)
2. Führe externes Zahlungssystem aus
3. Schreibe in die Datenbank, das die Zahlung durchgeführt worden ist
(Die Zahlung soll nur beim ersten Mal durchgeführt werden. Danach kann er den Service ein weiteres Mal kostenlos in Anspruch nehmen)

wenn der kunde doppelt klickt (machen einige), dann wird das formular zweimal abgeschickt.
prozess P1 guckt nach, ob der kunde schon bezahlt hat. nein. zahlung.
prozess P2 guckt nach, ob der kunde schon bezahlt hat. nein. zahlung.
P1 schreibt in datenbank, dass die zahlung durchgeführt wurde.
P2 schreibt in datenbank, dass die zahlung durchgeführt wurde.
du siehst also, dein problem hat sich nicht verändert. du musst transaktionen
verwenden. oder die tabellen locken.
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem
Gast Gast
 2007-08-20 14:52
#98413 #98413
Da ich eine kostenlose MYSQL DB der Version 4.018 Benutzer kommen die Transaktionen leider nicht in Frage (auch wenn das natürlich die eleganteste Lösung wäre).

Wie sieht das denn vielleicht mit Semaphoren aus, die ich abhängig von der Kundenid einführe.

Also das pro Kundenid nur eine Scriptinstanz den Block x betreten darf und die andere so lange warten muss, bis die erste den Block wieder verlassen hat. Weiß einer von euch, ob es da eine Unterstützung in Perl gibt? Vielleicht ein Modul o.ä.?
Gast Gast
 2007-08-20 14:55
#98414 #98414
Wären natürlich wenn nur pseudo-Semaphoren, da die ja eigentlich auf Prozessen beruhen...
pq
 2007-08-20 15:27
#98417 #98417
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
Gast+2007-08-20 12:52:03--
Da ich eine kostenlose MYSQL DB der Version 4.018 Benutzer kommen die Transaktionen leider nicht in Frage

wieso das nicht? InnoDB kann transaktionen, auch in mysql 4
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem
<< >> 9 Einträge, 1 Seite



View all threads created 2007-08-20 12:02.