Tot nu toe gaat het goed, dit zal in ieder geval voorkomen dat de gebruiker in meerdere sessies afrekent (meerdere keren proberen dezelfde kaart af te rekenen - goed om dubbelklikken te verwerken.)
Hoe controleer je? Met een standaard SELECT
of met een SELECT ... FOR UPDATE
? Op basis van stap 5 vermoed ik dat u een gereserveerde kolom over het item of iets dergelijks aan het controleren bent.
Het probleem hier is dat de SELECT ... FOR UPDATE
in stap 2 wordt de FOR UPDATE
NOT NIET toegepast sluit op al het andere. Het is alleen van toepassing op wat is SELECT
ed:het cart-item
tafel. Op basis van de naam wordt dat voor elke winkelwagen/gebruiker een ander record. Dit betekent dat andere transacties NIET worden geblokkeerd om door te gaan.
Als u het bovenstaande volgt, op basis van de informatie die u heeft verstrekt, kan het gebeuren dat meerdere mensen hetzelfde artikel kopen, als u SELECT ... FOR UPDATE
niet gebruikt. bij stap 3.
Voorgestelde oplossing
- Begin transactie
SELECT ... FOR UPDATE
hetcart-item
tafel.
Dit zal een dubbelklik blokkeren voor het uitvoeren. Wat u hier selecteert, zou een soort "winkelwagen besteld" kolom moeten zijn. Als u dit doet, zal een tweede transactie hier pauzeren en wachten tot de eerste is voltooid, en lees dan het resultaat wat de eerste in de database heeft opgeslagen.
Zorg ervoor dat u het afrekenproces hier beëindigt als het cart-item
tafel zegt dat het al is besteld.
SELECT ... FOR UPDATE
de tabel waarin u registreert of een item is gereserveerd.
Dit zorgt ervoor dat ANDERE winkelwagentjes/gebruikers deze items niet kunnen lezen.
Op basis van het resultaat, als de items niet zijn gereserveerd, gaat u verder:
-
UPDATE ...
de tabel in stap 3 en markeer het item als gereserveerd. Doe een andereINSERT
s enUPDATE
s die je ook nodig hebt. -
Betaling maken. Voer een terugdraaiing uit als de betalingsservice zegt dat de betaling niet is gelukt.
-
Noteer de betaling, indien succesvol.
-
Transactie vastleggen
Zorg ervoor dat u niets doet dat zou kunnen mislukken tussen stap 5 en 7 (zoals het verzenden van e-mails), anders zou u kunnen eindigen met een betaling zonder dat deze wordt geregistreerd, in het geval dat de transactie wordt teruggedraaid.
Stap 3 is de belangrijke stap om ervoor te zorgen dat twee (of meer) mensen niet hetzelfde artikel proberen te bestellen. Als twee mensen het toch proberen, zal de 2e persoon zijn webpagina laten "hangen" terwijl de eerste wordt verwerkt. Wanneer de eerste klaar is, leest de 2e de kolom "gereserveerd" en kunt u een bericht naar de gebruiker terugsturen dat iemand dat item al heeft gekocht.
Betaling in transactie of niet
Dit is subjectief. Over het algemeen wilt u transacties zo snel mogelijk sluiten, om te voorkomen dat meerdere mensen tegelijk worden uitgesloten van interactie met de database.
In dit geval wil je echter wel dat ze wachten. Het is alleen een kwestie van hoe lang.
Als u ervoor kiest om de transactie vóór betaling vast te leggen, moet u uw voortgang in een tussenliggende tabel vastleggen, de betaling uitvoeren en vervolgens het resultaat vastleggen. Houd er rekening mee dat als de betaling mislukt, u de artikelreserveringsrecords die u heeft bijgewerkt, handmatig ongedaan moet maken.
SELECTEER ... VOOR UPDATE op niet-bestaande rijen
Een woord van waarschuwing, voor het geval uw tabelontwerp het invoegen van rijen omvat waar u eerder moet SELECT ... FOR UPDATE
:Als een rij niet bestaat, zal die transactie GEEN andere transacties laten wachten, als ze ook SELECT ... FOR UPDATE
dezelfde niet-bestaande rij.
Zorg er dus voor dat u uw verzoeken altijd serialiseert door een SELECT ... FOR UPDATE
. uit te voeren op een rij waarvan je als eerste weet dat die bestaat. Dan kun je SELECT ... FOR UPDATE
op de rij die al dan niet bestaat. (Probeer niet gewoon een SELECT
te doen op de rij die al dan niet bestaat, aangezien u de status van de rij leest op het moment dat de transactie begon, niet op het moment dat u de SELECT
uitvoert . Dus SELECT ... FOR UPDATE
op niet-bestaande rijen is nog steeds iets dat u moet doen om de meest actuele informatie te krijgen, maar houd er rekening mee dat andere transacties hierdoor niet moeten wachten.)