Vermijden dat een record wordt overschreven.
De verhuring van standen op onze tweedehandsbeurs gebeurt online. Ik heb een tabel aangemaakt waarin elke record een stand is. In elke record komen de gegevens van de huurder en een veld dat aangeeft of deze stand nog vrij is.
Via een eerste pagina waarin de nog vrije standen getoond worden, komen de kandidaat-huurders op een formulier-pagina terecht. Als de stand inmiddels toch verhuurd blijkt te zijn, krijgt men deze boodschap ("tafel is reeds verhuurd") en kan men terug naar de eerste pagina.
Bij het posten van het formulier wordt de stand gereserveerd en worden de gegevens van de huurder in de record geplaatst.
Nu heb ik ondervonden dat als er meerdere personen tegelijkertijd hun gegevens invullen op deze pagina (voor dezelfde stand dus), de gegevens van de persoon die het laatst zijn gegevens verzend deze van de vorige overschrijft.
Ik heb dit proberen te voorkomen door de pagina elke 90s te laten refreshen om na te gaan of de tafel nog vrij is maar dit is natuurlijk maar een lapmiddel.
Wat kan ik doen op dit overschrijven te voorkomen?
Testen voordat je het database-update-statement uitvoert: is dit record echt nog vrij?
alleen ... de syntax is een ??
In het proces kun je het misschien als volgt oplossen:
- kiest de huurder een stand, dan haal je direct met ajax de bezetting op; de servlet die die bezetting afgeeft, vergrendelt eerst het record
- bij de tweede huurder die die stand kiest, loopt de servlet tegen de lock aan en kan melden "iemand probeert deze stand te huren". Doe iets slims (een melding wanneer de eerste huurder een beslissing heeft genomen? timeout-toestanden)
Dat vraagt om een lock-mechaniek voor een record. 't Is even inlezen, "race condition" is een van je trefwoorden.
Een andere aanpak is dat je alle reserveringen als aparte records noteert, als het ware als subrecord van de stand. Dan is elke insert een individu, krijgt daarmee (wanneer je een autonummer-veld in de tabel hebt) een uniek volgnummer, en (wanneer je ook now() in de tabel opslaat) een duidelijk moment van registreren. Tegen alle pogingen daarna kun je dus zeggen "sorry, te laat" -- en dan klantvriendelijk vertaald.
Hetgeen je in je "andere aanpak" voorstelt, had ik al gedeeltelijk gedaan. Ik heb een tweede tabel gemaakt waarin nog eens alle gegevens opgeslagen worden (met autonummering en NOW-veld). Op die manier heb ik trouwens het probleem ontdekt. Ik ga eens verder zoeken hoe ik deze controletabel kan gebruiken om de toegang tot de record in de andere tabel tijdelijk te vergrendelen.
Gewijzigd op 24/12/2010 12:48:06 door John D
http://www.webcheatsheet.com/php/record_locking_in_web_applications.php
Ik denk dat dit artikel mijn vraag goed omschrijft.
Gewijzigd op 26/12/2010 21:42:41 door P Dries