sql >> Database >  >> RDS >> Mysql

Hoe transacties en vergrendelingen correct te gebruiken om de database-integriteit te waarborgen?

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

  1. Begin transactie
  2. SELECT ... FOR UPDATE het cart-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.

  1. 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:

  1. UPDATE ... de tabel in stap 3 en markeer het item als gereserveerd. Doe een andere INSERT s en UPDATE s die je ook nodig hebt.

  2. Betaling maken. Voer een terugdraaiing uit als de betalingsservice zegt dat de betaling niet is gelukt.

  3. Noteer de betaling, indien succesvol.

  4. 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.)



  1. Hoe de tabel in Oracle bij te werken

  2. Schrijf GeoDataFrame in SQL Database

  3. MySQL-groep per uur

  4. Geeft COUNT(*) altijd een resultaat?