Så langt så godt, dette vil i det mindste forhindre brugeren i at foretage checkout i flere sessioner (flere gange at prøve at betale det samme kort - godt at håndtere dobbeltklik.)
Hvordan tjekker du? Med en standard SELECT
eller med en SELECT ... FOR UPDATE
? Baseret på trin 5 gætter jeg på, at du tjekker en reserveret kolonne på varen eller noget lignende.
Problemet her er, at SELECT ... FOR UPDATE
i trin 2 vil IKKE anvende SELECT
ed:indkøbsvognen
bord. Baseret på navnet vil det være en forskellig post for hver vogn/bruger. Det betyder, at andre transaktioner IKKE vil blive blokeret fra at fortsætte.
Efter ovenstående, baseret på de oplysninger, du har givet, kan du ende med, at flere personer køber den samme vare, hvis du ikke bruger VÆLG ... TIL OPDATERING
på trin 3.
Foreslået løsning
- Begynd transaktionen
VÆLG ... TIL OPDATERING
indkøbsvognen
tabel.
Dette vil låse et dobbeltklik fra at køre. Det, du vælger her, bør være en slags "vognbestilt" kolonne. Hvis du gør dette, vil en anden transaktion pause her og vente på, at den første er færdig, og derefter læse resultatet, hvad den først gemte i databasen.
Sørg for at afslutte betalingsprocessen her, hvis indkøbskurv-varen
tabellen siger, at den allerede er bestilt.
VÆLG ... TIL OPDATERING
tabellen, hvor du registrerer, hvis en vare er blevet reserveret.
Dette vil låse ANDRE vogne/brugere fra at kunne læse disse varer.
Baseret på resultatet, hvis varerne ikke er reserveret, fortsæt:
-
OPDATERING ...
tabellen i trin 3, og markerer varen som reserveret. Gør en hvilken som helst andenINSERT
s ogOPDATERING
s du også har brug for. -
Foretag betaling. Udsted en tilbagerulning, hvis betalingstjenesten siger, at betalingen ikke fungerede.
-
Registrer betaling, hvis succes.
-
Forpligt transaktion
Sørg for, at du ikke gør noget, der muligvis mislykkes mellem trin 5 og 7 (som at sende e-mails), ellers kan du ende med, at de foretager en betaling, uden at den bliver registreret, i tilfælde af at transaktionen bliver rullet tilbage.
Trin 3 er det vigtige skridt med hensyn til at sikre, at to (eller flere) personer ikke forsøger at bestille den samme vare. Hvis to personer prøver, vil den anden person ende med at få deres webside "hængt", mens den behandler den første. Når den første er færdig, vil den anden læse kolonnen "reserveret", og du kan returnere en besked til brugeren om, at nogen allerede har købt den vare.
Betaling i transaktion eller ej
Dette er subjektivt. Generelt vil du gerne lukke transaktioner så hurtigt som muligt for at undgå, at flere personer bliver låst ude fra at interagere med databasen på én gang.
Men i dette tilfælde vil du faktisk have dem til at vente. Det er bare et spørgsmål om hvor længe.
Hvis du vælger at forpligte transaktionen før betaling, skal du registrere dine fremskridt i en mellemliggende tabel, køre betalingen og derefter registrere resultatet. Vær opmærksom på, at hvis betalingen mislykkes, skal du manuelt fortryde de varereservationsregistreringer, som du opdaterede.
VÆLG ... TIL OPDATERING på ikke-eksisterende rækker
Bare en advarsel, hvis dit tabeldesign involverer indsættelse af rækker, hvor du skal tidligere VÆLG ... TIL OPDATERING
:Hvis en række ikke eksisterer, vil den transaktion IKKE få andre transaktioner til at vente, hvis de også VÆLG ... TIL OPDATERING
den samme ikke-eksisterende række.
Så sørg for altid at serialisere dine anmodninger ved at gøre en SELECT ... FOR UPDATE
på en række, som du ved eksisterer først. Så kan du VÆLG ... TIL OPDATERING
på rækken, der måske eller måske ikke eksisterer endnu. (Forsøg ikke kun at lave en SELECT
på rækken, der måske eksisterer eller ikke eksisterer, da du vil læse rækkens tilstand på det tidspunkt, hvor transaktionen startede, ikke i det øjeblik, du kører SELECT
. Så VÆLG ... TIL OPDATERING
på ikke-eksisterende rækker er stadig noget, du skal gøre for at få den mest opdaterede information, bare vær opmærksom på, at det ikke vil få andre transaktioner til at vente.)