Beste manieren om met records en locking om te gaan?

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • Hatsieflatsie
  • Registratie: Oktober 2011
  • Laatst online: 09-10 09:52
Het kan voorkomen dat een database record door een gebruiker via een webinterface bewerkt wordt. Ik wil dan voorkomen, dat iemand anders dezelfde record op dezelfde moment ook bewerkt.

Daar bestaan er verschillende methoden voor, met locking.Wanneer ik mij inlees in de methoden, zit ik mij af te vragen wat een battle-proven beste methode is.

Zo heb je bijvoorbeeld in dezelfde tabel naast de record, dat bewerkt wordt, een veld "locked" met positieve of negatieve waarde. Wanneer dit veld een positieve waarde is, dan is de record locked.
Maar wat als de gebruiker ondertussen de browser afsluit, zonder de record op te slaan? Dan blijft dit record voor andere gebruikers altijd locked, en kan niemand meer erbij. :X.

Ik zat te denken om een apart tabel (locking-tabel) te hanteren, met daarin slechts de ID's en date-time waarden. De ID's zijn gekoppeld aan de correspodenderende ID's in de records tabel.
Om minuut wordt er een Ajax request naar een script uitgevoerd, met daarin de ID. De ID in locking-tabel wordt vervolgens bijgewerkt met meest recente tijdstip.

Wanneer een record in de locking tabel voorkomt, dan is deze locked.

Nachts draait een cronjob. Die cronjob schoont alle records in de locking tabel, die ouder zijn dan 2 minuten. Zo heb je het probleem niet dat een record in de browser nog niet opgeslagen is, terwijl de client inactief is. Maar dit lijkt mij vrij omslachtig, en er zullen wel situaties zijn die ik nog niet voorzien heb.

Zijn er hier nog Tweakers die eerder met locking implementaties gewerkt hebben, en hier kunnen delen wat voor hen het beste gewerkt heeft?

Acties:
  • 0 Henk 'm!

  • Xudonax
  • Registratie: November 2010
  • Laatst online: 07-10 13:38
Stap één is om een fatsoenlijke database engine te gebruiken welke "atomic" de rijen kan bijwerken. Ik herinner me dat MySQL dit vroeger niet was met MyISAM, geen idéé eigenlijk hoe dat nu is. Engines zoals PostgreSQL, SQL Server, Oracle etc. doen dit allemaal wel voor zover ik weet. Je zou hierbij vooral moeten kijken naar ACID ondersteuning.

Vervolgens zou ik een JOIN besparen en de locking niet zozeer een ja/nee waarde maken met een losse datum/tijd tabel, maar juist de datum/tijd gebruiken als teken of iets gelocked is of niet. Het is geen data die je deelt over verschillende rijen (zoals bijvoorbeeld gebruikersinformatie, een adres, een product etc.) dus zie ik geen directe aanleiding om dit eruit te halen.

Vervolgens zou ik een UPDATE statement maken in de trent van UPDATE [TABLE] WHERE id = [X] AND locked = NULL. Op deze manier faalt je UPDATE statement op het moment dat een ander process je voor is qua locking. Wel moet je dit vervolgens goed afvangen, en aan de gebruiker tonen hoe en wat.

Ik weet overigens niet wat voor product dit voor is, maar als het iets is waarbij er meerdere mensen van één bedrijf/organisatie erin werken zou je kunnen overwegen om juist wél een aparte locking tabel te doen, en hierbij ook op te slaan welke gebruiker er momenteel aan het bewerken is. Dan zou je (binnen hetzelfde bedrijf/dezelfde organisatie) kunnen tonen dat het momenteel niet mogelijk is om te bewerken omdat Jantje er momenteel in bezig is. Zo ontstaat er ook meteen een stukje sociale controle op het niet locked achterlaten van je spullen. In dit geval zou de LOCKED kolom een foreign key zijn naar de locking tabel, waarin je vervolgens een datum/tijd opslaat en een foreign key naar de user tabel. Hierbij zou je wel alles in een transactie moeten stoppen, of mogelijk zelfs kunnen kijken naar een stored procedure om wat meer kracht in je database engine te verstoppen.

Neem dat verstoppen trouwens wel vrij letterlijk, want hoewel je code (hopelijk) netjes in versiebeheer zit is dit vaak niet het geval met stored procedures. Zorg er dus voor dat er goed gedocumenteerd is dat je een bepaalde functionaliteit in je database hebt zitten ;)

Acties:
  • 0 Henk 'm!

  • Xiphalon
  • Registratie: Juni 2001
  • Laatst online: 11-10 15:15
Records timestampen inderdaad. Dus een kolom met daarin de timestamp laatste wijziging en het update-statement een where timestampkolom=<waardeToenDieUitDeDatabaseKwam>, en uiteraard ook weer de timestamp bijwerken. Aan de hand van het aantal gewijzigde records kan je dan zien of het gelukt is of niet.
Als je alles netjes in een transactie doet, kan je óf alles laten slagen óf alles terugrollen en de gebruiker informeren (of als je van ingewikkelde problemen houdt, eerst proberen automatisch de wijzigingen die al in de database staan ook te verwerken).

Ander model is dat je (ook / alleen) de wijzigingen zélf opslaat, dan maken dubbele wijzigingen niet uit, er staan er gewoon 2 in de historie van het object. Performance op objecten met veel wijziginen wordt hier interessant :p

Acties:
  • +2 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Alternatief kan je ook een timestamp laatste wijziging of versienummer in elke row stoppen, zodat je bij de latere submit kan weigeren, waarschuwen of zelfs de diff kan tonen.

Ivm race condities moet je dan wel de update actie laten locken, maar dan heb je geen lange termijn lock nodig voor de gehele tijd dat een form (misschien :X ) nog open staat en geen staat die je moet opruimen. Timestamp laatst gewijzigd is wellicht sowieso al een nuttig gegeven.

Overigens, als de update acties op elkaar wachten heb je misschien ook t probleem niet meer: als de entity zelf controleert of deze valide is, mag de 2e set wijzigingen misschien alsnog op basis van de huidige staat, of is deze concreter af te keuren (i.e. 'User is gedeactiveerd, wijziging niet mogelijk' als de eerder edit dus iemand banned etc)

{signature}


Acties:
  • 0 Henk 'm!

  • ajakkes
  • Registratie: Maart 2004
  • Laatst online: 16-05 22:32

ajakkes

👑

Als gebruiker 1 vind dat A, B moet zijn en gebruiker 2 vind dat het C moet zijn. Moet gebruiker 2 dan van jou wachten tot gebruiker 1 heeft opgeslagen?

En zijn inderdaad situaties waar dat zo is. Bijvoorbeeld waardes die steeds uitgebreid/aangevuld worden in plaats van overschreven.

Maar vaak wil je dan ook versie beheer op de data. Welke gebruiker heeft welk stukje tekst toegevoegd.

Is alleen bewaken van een wijziging van persoon 2 op het moment dat persoon 1 bezig is, wat je doel is?

👑


Acties:
  • 0 Henk 'm!

  • Onbekend
  • Registratie: Juni 2005
  • Laatst online: 00:12

Onbekend

...

Met webapplicaties moet je eigenlijk geen records locken. Zeker niet voor langere tijd.
Je moet vlak voor het opslaan controleren of het record was gewijzigd door iemand anders en daarvan een melding of aanpas-advies geven.

Speel ook Balls Connect en Repeat


Acties:
  • 0 Henk 'm!

  • Hatsieflatsie
  • Registratie: Oktober 2011
  • Laatst online: 09-10 09:52
Bedankt voor je post. Echter, ik weet nog steeds niet welke implementatie het beste zou zijn.
Xudonax schreef op zondag 19 juni 2016 @ 00:40:
Stap één is om een fatsoenlijke database engine te gebruiken welke "atomic" de rijen kan bijwerken.
Atomic houdt toch in dat data niet verdeeld of gesplitst kan worden in meerdere delen?
Ik herinner me dat MySQL dit vroeger niet was met MyISAM, geen idéé eigenlijk hoe dat nu is. Engines zoals PostgreSQL, SQL Server, Oracle etc. doen dit allemaal wel voor zover ik weet. Je zou hierbij vooral moeten kijken naar ACID ondersteuning.(

Vervolgens zou ik een JOIN besparen en de locking niet zozeer een ja/nee waarde maken met een losse datum/tijd tabel, maar juist de datum/tijd gebruiken als teken of iets gelocked is of niet. Het is geen data die je deelt over verschillende rijen (zoals bijvoorbeeld gebruikersinformatie, een adres, een product etc.) dus zie ik geen directe aanleiding om dit eruit te halen.

Vervolgens zou ik een UPDATE statement maken in de trent van UPDATE [TABLE] WHERE id = [X] AND locked = NULL. Op deze manier faalt je UPDATE statement op het moment dat een ander process je voor is qua locking. Wel moet je dit vervolgens goed afvangen, en aan de gebruiker tonen hoe en wat.
Daarom stelde ik wat anders voor, aangezien sommige gebruikers hun bewerkingsessie halverwege kunnen afbreken. Dan zit je nog steeds met een locked-waarde in je record, waardoor andere gebruikers de record niet kunnen updaten.w
Ik weet overigens niet wat voor product dit voor is, maar als het iets is waarbij er meerdere mensen van één bedrijf/organisatie erin werken zou je kunnen overwegen om juist wél een aparte locking tabel te doen, en hierbij ook op te slaan welke gebruiker er momenteel aan het bewerken is. Dan zou je (binnen hetzelfde bedrijf/dezelfde organisatie) kunnen tonen dat het momenteel niet mogelijk is om te bewerken omdat Jantje er momenteel in bezig is.
Vandaar m'n voorstel. Hoe update je de locked tabel, en hoe kun je vaststellen dat de gebruiker niet meer actief is? Ik stelde een strategie voor, maar daar zie ik geen verbeterpunten op komen.
of mogelijk zelfs kunnen kijken naar een stored procedure om wat meer kracht in je database engine te verstoppen.

Neem dat verstoppen trouwens wel vrij letterlijk, want hoewel je code (hopelijk) netjes in versiebeheer zit is dit vaak niet het geval met stored procedure.
Interessante gedachte. Heb je een voorbeeld op welke wijze ik de locking implementatie kan combineren met een stored procedure?

Acties:
  • 0 Henk 'm!

  • Hatsieflatsie
  • Registratie: Oktober 2011
  • Laatst online: 09-10 09:52
Xiphalon schreef op zondag 19 juni 2016 @ 09:44:
Records timestampen inderdaad. Dus een kolom met daarin de timestamp laatste wijziging en het update-statement een where timestampkolom=<waardeToenDieUitDeDatabaseKwam>, en uiteraard ook weer de timestamp bijwerken. Aan de hand van het aantal gewijzigde records kan je dan zien of het gelukt is of niet.
Als je alles netjes in een transactie doet, kan je óf alles laten slagen óf alles terugrollen en de gebruiker informeren (of als je van ingewikkelde problemen houdt, eerst proberen automatisch de wijzigingen die al in de database staan ook te verwerken).

Ander model is dat je (ook / alleen) de wijzigingen zélf opslaat, dan maken dubbele wijzigingen niet uit, er staan er gewoon 2 in de historie van het object. Performance op objecten met veel wijziginen wordt hier interessant :p
Als ik het goed begrijp: gebruiker A vraagt record 1 op. Timestamp is dan 10:00 uur.

Gebruiker B vraagt later om 10:30 uur ook record 1 op. En ziet dat timestamp op 10:00 uur staat. Hoe weet-ie dat de record dan afgerond is en weer bewerkt mag worden? Hoe ziet-ie dan dat de record locked is?

Acties:
  • 0 Henk 'm!

  • Hatsieflatsie
  • Registratie: Oktober 2011
  • Laatst online: 09-10 09:52
ajakkes schreef op zondag 19 juni 2016 @ 11:28:
Als gebruiker 1 vind dat A, B moet zijn en gebruiker 2 vind dat het C moet zijn. Moet gebruiker 2 dan van jou wachten tot gebruiker 1 heeft opgeslagen?
Zou dat anders moeten zijn? Gebruiker 1 was immers eerder.

Echter, wat als de gebruiker 1 halverwege z'n sessie verlaat. Dan moet gebruiker 2 een eeuwigheid wachten totdat de record vrijgegeven wordt.
Is alleen bewaken van een wijziging van persoon 2 op het moment dat persoon 1 bezig is, wat je doel is?
Niet per sé, maar wel als startpunt. Echter, dit moet geleidelijk groeien naar steeds ingewikkeldere implementaties, aangezien de functionaliteit van het systeem steeds meer uitgebreid wordt. Dan vraag ik mij af wat een battle-proven implementatie van locking is.

Acties:
  • 0 Henk 'm!

  • Kwistnix
  • Registratie: Juni 2001
  • Laatst online: 23:15
Voutloos schreef op zondag 19 juni 2016 @ 09:45:
Alternatief kan je ook een timestamp laatste wijziging of versienummer in elke row stoppen, zodat je bij de latere submit kan weigeren, waarschuwen of zelfs de diff kan tonen.
Dit. En dan in combinatie met optimistic locking i.pv. pessimistic locking, tenminste dat is wel de meer efficiënte locking strategy en vaak afdoende in use cases zoals door jou beschreven. Versioning van records integreert ook vaak goed met ORM oplossingen, maar ik weet niet of je daar gebruik van maakt.

Acties:
  • 0 Henk 'm!

  • Hatsieflatsie
  • Registratie: Oktober 2011
  • Laatst online: 09-10 09:52
Onbekend schreef op zondag 19 juni 2016 @ 11:33:
Je moet vlak voor het opslaan controleren of het record was gewijzigd door iemand anders en daarvan een melding of aanpas-advies geven.
Hoe doe je dat dan vervoglens?

Stel, gebruiker 1 ontvangt data, wat A is.

Gebruiker 2 vraagt ook data op, wat A is.

Gebruiker 1 wijzigt de waarde A in de tussentijd naar B.

Gebruiker 2 wijzigt later de openstaande record met A-waarde naar C.

Moet de gebruiker 2 geblokkeerd worden? En waarom dan?

Acties:
  • 0 Henk 'm!

  • Koenvh
  • Registratie: December 2011
  • Laatst online: 11-10 00:28

Koenvh

Hier tekenen: ______

Hatsieflatsie schreef op zondag 19 juni 2016 @ 16:16:
[...]

Zou dat anders moeten zijn? Gebruiker 1 was immers eerder.

Echter, wat als de gebruiker 1 halverwege z'n sessie verlaat. Dan moet gebruiker 2 een eeuwigheid wachten totdat de record vrijgegeven wordt.

[...]
Niet per sé, maar wel als startpunt. Echter, dit moet geleidelijk groeien naar steeds ingewikkeldere implementaties, aangezien de functionaliteit van het systeem steeds meer uitgebreid wordt. Dan vraag ik mij af wat een battle-proven implementatie van locking is.
Dan kun je in plaats van één keer locken en daarna unlocken nadat het is afgerond, hem elke 30 seconden opnieuw laten locken. Mocht iemand de sessie dan geforceerd sluiten wordt hij alsnog na 30 seconden vrijgegeven.

🠕 This side up


Acties:
  • 0 Henk 'm!

  • Hatsieflatsie
  • Registratie: Oktober 2011
  • Laatst online: 09-10 09:52
Koenvh schreef op zondag 19 juni 2016 @ 16:20:
[...]

Dan kun je in plaats van één keer locken en daarna unlocken nadat het is afgerond, hem elke 30 seconden opnieuw laten locken. Mocht iemand de sessie dan geforceerd sluiten wordt hij alsnog na 30 seconden vrijgegeven.
En dat zou dus kunnen verlopen via een Ajax call die clientside continu afgevuurd wordt naar de database?

Dit betekent wel dat een cronjob ieder 30 seconden de records moet controleren op ouderdom van >30 seconden, om vervolgens in vrijgeven te wijzigen. Dat lijkt mij te belastend voor het systeem?

Acties:
  • 0 Henk 'm!

  • Koenvh
  • Registratie: December 2011
  • Laatst online: 11-10 00:28

Koenvh

Hier tekenen: ______

Hatsieflatsie schreef op zondag 19 juni 2016 @ 16:22:
[...]
En dat zou dus kunnen verlopen via een Ajax call die clientside continu afgevuurd wordt naar de database?

Dit betekent wel dat een cronjob ieder 30 seconden de records moet controleren op ouderdom van >30 seconden, om vervolgens in vrijgeven te wijzigen. Dat lijkt mij te belastend voor het systeem?
Zoiets, al hoeft een cronjob niet per se. Je kunt ook een tabel bijhouden met het locken, en dan controleren of de record daarin voorkomt met een timestamp van minder dan 30 seconden geleden. De AJAX call kan dan de timestamp vernieuwen

[ Voor 3% gewijzigd door Koenvh op 19-06-2016 16:26 ]

🠕 This side up


Acties:
  • 0 Henk 'm!

  • Onbekend
  • Registratie: Juni 2005
  • Laatst online: 00:12

Onbekend

...

Hatsieflatsie schreef op zondag 19 juni 2016 @ 16:20:
[...]
Hoe doe je dat dan vervolgens?

Stel, gebruiker 1 ontvangt data, wat A is.

Gebruiker 2 vraagt ook data op, wat A is.

Gebruiker 1 wijzigt de waarde A in de tussentijd naar B.

Gebruiker 2 wijzigt later de openstaande record met A-waarde naar C.

Moet de gebruiker 2 geblokkeerd worden? En waarom dan?
Als twee verschillende gebruikers het zelfde record aanpassen, zijn er drie mogelijke situaties:
1. Beide gebruikers passen twee verschillende velden aan.
2. Beide gebruikers passen het zelfde veld aan, en de gebruikers geven allebei het veld de zelfde nieuwe waarde.
3. Beide gebruikers passen het zelfde veld aan, maar de gebruikers geven allebei het veld een totale andere waarde.

1.
Niets aan de hand. Gewoon de update uitvoeren.
2.
Ook niets aan de hand. Het resultaat wat de laatste gebruiker wilde hebben is namelijk al gelijk met wat er in de database staat.
3.
Dit is een klein probleempje. Maar waarom zou de ene gebruiker het veld naar de ene waarde willen updaten terwijl de andere gebruiker het veld naar de andere waarde willen updaten?
Dus geef de laatste gebruiker de melding dat het record al is gewijzigd, en geef meteen de nieuwste waarden door zodat hij zijn invoer kan vergelijken met wat door de andere gebruiker in de database is gezet. (Als hij daarna opnieuw zijn wijzigingen wil verzenden kan dat alsnog, want hij had zojuist de gewijzigde waarden binnengekregen waarmee het updatestatement kan worden uitgevoerd.)

Speel ook Balls Connect en Repeat


Acties:
  • 0 Henk 'm!

  • Hatsieflatsie
  • Registratie: Oktober 2011
  • Laatst online: 09-10 09:52
Koenvh schreef op zondag 19 juni 2016 @ 16:25:
[...]

Zoiets, al hoeft een cronjob niet per se. Je kunt ook een tabel bijhouden met het locken, en dan controleren of de record daarin voorkomt met een timestamp van minder dan 30 seconden geleden. De AJAX call kan dan de timestamp vernieuwen
Ik denk dat daar nog haken en ogen aan zitten. Wat als de browser bij gebruiker 1 vastloopt? Dan worden er ook geen Ajax calls verstuurd. Ondertussen gaat gebruiker 2 dan z'n record editten.

Gebruiker 1 vernieuwt de pagina vervolgens, maar hij is dan ook zijn record kwijt.

Acties:
  • 0 Henk 'm!

  • Hatsieflatsie
  • Registratie: Oktober 2011
  • Laatst online: 09-10 09:52
Onbekend schreef op zondag 19 juni 2016 @ 16:34:
[...]

Als twee verschillende gebruikers het zelfde record aanpassen, zijn er drie mogelijke situaties:
1. Beide gebruikers passen twee verschillende velden aan.
2. Beide gebruikers passen het zelfde veld aan, en de gebruikers geven allebei het veld de zelfde nieuwe waarde.
3. Beide gebruikers passen het zelfde veld aan, maar de gebruikers geven allebei het veld een totale andere waarde.

1.
Niets aan de hand. Gewoon de update uitvoeren.
De query kan als volgt uitzien: UPDATE [TABLE] WHERE id = [X] AND locked = NULL.

Hoe moet dat als het 2 verschillende velden zijn? Er kan maar 1 referentiewaarde voor locked aangehouden worden (LOCKED voor veld 1, terwijl gebruiker veld 2 wilt bewerken).
3.
Dit is een klein probleempje. Maar waarom zou de ene gebruiker het veld naar de ene waarde willen updaten terwijl de andere gebruiker het veld naar de andere waarde willen updaten?
Je moet niet afvragen waarom gebruikers dat doen. Je moet veronderstellen dat dergelijke situaties kunnen optreden, en hoe daarmee omgegaan wordt zonder dat de data onbedoeld aangetast wordt dankzij meerdere gebruikers tegelijkertijd.
Dus geef de laatste gebruiker de melding dat het record al is gewijzigd
Hoe zie je zo'n tabelstructuur voor je? Waar moet in de database vermeld staan, dat de record in de tussentijd gewijzigd is, vergeleken met de input?

Acties:
  • 0 Henk 'm!

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
Hatsieflatsie schreef op zondag 19 juni 2016 @ 16:54:
[...]
Hoe zie je zo'n tabelstructuur voor je? Waar moet in de database vermeld staan, dat de record in de tussentijd gewijzigd is, vergeleken met de input?
Simpel, elk record heeft een last updated time. Bij het opvragen wordt die tijd ook mee opgevraagd en bij opslaan wordt die tijd ook weer meegestuurd (maar nu onder een andere naam)

Oftewel record A heeft een last updated van 10:00
Gebruiker 1 gaat het record ophalen en bijwerken en deze krijgt dus 10:00 mee
Gebruiker 2 gaat het record ophalen en bijwerken en deze krijgt dus 10:00 mee
Gebruiker 1 gaat het record opslaan en verandert daarmee de last updated time naar 10:05
Gebruiker 2 wil het record opslaan maar die krijgt een conflict, want de laatste versie die hij heeft is van 10:00 terwijl de database een versie van 10:05 heeft staan, oftewel er kan niet blind opgeslagen worden. Toon gebruiker 2 een diff view tussen de versie die hij wil opslaan en de versie van 10:05 en dan mag de gebruiker het uitzoeken / annuleren.

Vereist helemaal geen custom locks etc. Alleen een last updated time en een stukje logica.

Acties:
  • 0 Henk 'm!

  • johnkeates
  • Registratie: Februari 2008
  • Laatst online: 04-07 16:30
Met een webapplicatie kan je dat niet zo doen om dat er geen controle is over de applicatie flow.

De engine manier voor dit soort temporale clients/users is bij het opslaan een melding geven als de rij al gewijzigd was, en het opslaan annuleren. Daarna kan de gebruiker er alsnog voor kiezen om opnieuw te bewerken.

Voor documenten is dat anders, daar kan je wel een document locken, desnoods met een timeout.

Acties:
  • +1 Henk 'm!

  • Onbekend
  • Registratie: Juni 2005
  • Laatst online: 00:12

Onbekend

...

Je moet niet bijhouden welke regel gelocked is. Je zou eventueel wel kunnen bijhouden op welk tijdstip als laatste het record is opgehaald om te wijzigen. (Maar als de computer of internetverbinding uitvalt, dan kan iemand anders evengoed nog het records wijzigen.)

Ok, even een voorbeeldje:

Stel je een tabel met de naam Tabel1, en daarin staan drie kolommen: Kol1, Kol2 en Kol3. (Voor dit voorbeeld gaan we er van uit dat Kol1 de primary key is.)

Gebruiker 1 en 2 halen de regel op en die weten de inhoud van het record.
SELECT Kol1, Kol2, Kol3 FROM Table1 WHERE Kol1 = 'a'.

Het resultaat is dan 'a', 'b', 'c'.


Gebruiker 1 wil Kol2 aanpassen naar 'd'. Die zend dus via AJAX de oorspronkelijke waarden en de nieuwe waarde mee. Aan de serverkant wordt dan het volgende gegenereerd:
UPDATE Tabel1 SET Kol2 = 'd' WHERE Kol1 = 'a' AND Kol2 = 'b' AND Kol3 = 'c'.
Als er 1 record is geupdated, geef je succes terug. Als er 0 is geupdated, doe je weer
SELECT Kol1, Kol2, Kol3 FROM Table1 WHERE Kol1 = 'a'. Dan ga je kijken of de kolommen die aangepast hadden moeten worden toevallig de zelfde waarden al hebben in de database. In dat geval geef je ook succes terug, met een extra melding dat iemand anders die waarde ook al had ingevuld.
Als de waarden niet overeen komen, dan geef je de het resultaat van SELECT Kol1, Kol2, Kol3 FROM Table1 WHERE Kol1 = 'a' gewoon weer terug (via AJAX) naar de webbrowser, en mag de gebruiker zelf bepalen of zijn waarde beter was dan die van de ander.


Zolang je diezelfde opgehaalde waarden weer meegeeft met het update-statement gaat dit altijd goed.

Speel ook Balls Connect en Repeat


Acties:
  • 0 Henk 'm!

  • ajakkes
  • Registratie: Maart 2004
  • Laatst online: 16-05 22:32

ajakkes

👑

Is de record code, dan is het ongewenst dat gebruiker B de code van A overschrijft.

Is het een Wiki achtig artikel dan is het voldoende om gebruiker B te vertellen dat er al een wijziging was die gebruiker A had gedaan die daarmee overschreven wordt.

Is het een vaste waarde zoals een naam of datum dan hebben beide gebruikers net zo veel recht om de aanpassing door te voeren en hoef je hier geen rekening mee te houden.

Bedenk goed dat locking, en zeker verkeerde locking meer ergernis oplevert dan het oplost. En vraag je af hoe vaak gebruikers dezelfde record op dezelfde tijd gaan aanpassen.

👑


Acties:
  • 0 Henk 'm!

  • TheNephilim
  • Registratie: September 2005
  • Laatst online: 09-10 15:13

TheNephilim

Wtfuzzle

Even heel simpel...

HTML:
1
2
3
4
5
6
7
<form>
    <input type="hidden" name="updated_at" value="2016-06-20 09:00:00" />

    <input type="text" name="data" value="A" />

    <button type="submit">Opslaan</button>
</form>


PHP:
1
2
3
4
5
6
if ($input->updated_at !== $db_record->updated_at) {
    // Foutmelding geven oid.
}
else {
    // Gewoon opslaan in de database.
}


Bij het openen van de te bewerken data heb je vast een formulier. Daarin neem je een veld op met het tijdstip waarop het record als laatst gewijzigd is. Bij het opslaan van 'data' kijk je of 'updated_at' nog gelijk is aan wat er in de database staan. Zo niet dan weet je dat het record tussentijds aangepast is.

Mocht het voorkomen dat twee personen tegelijkertijd het formulier openen, dan klopt bij diegene die het record als laatste opslaat de 'updated_at' niet meer. Die komt niet meer overeen met wat er in de database staat.

Op dat moment zijn er natuurlijk verschillende manieren om dit verder af te handelen. Je kunt met revisies werken, of simpelweg een foutmelding geven en de gegevens in eerste instantie gewoon niet opslaan, misschien een soort van overschrijven bevestiging.

[ Voor 7% gewijzigd door TheNephilim op 20-06-2016 10:36 ]


Acties:
  • 0 Henk 'm!

  • L01
  • Registratie: December 2003
  • Laatst online: 22:48

L01

Wat TheNephilim voorstelt is niet helemaal veilig.

De waarde in het hiddenfield kan aangepast worden door de gebruiker naar een later tijdstip waardoor wijzigingen kunnen worden overschreven.

Ik zou een veld openemen bij het record met daarin een unguessable key die wordt gewijzigd na elke update. Deze key neem je ook op in je formulier. Na een post controleer je of de waarde nog hetzelfde is. Als dit niet het geval is dan toon je een melding aan de gebruiker.

Hi, I'm a signature virus. Put me in your signature to help me spread.


Acties:
  • 0 Henk 'm!

  • ajakkes
  • Registratie: Maart 2004
  • Laatst online: 16-05 22:32

ajakkes

👑

L01 schreef op maandag 20 juni 2016 @ 10:43:
Wat TheNephilim voorstelt is niet helemaal veilig.

De waarde in het hiddenfield kan aangepast worden door de gebruiker naar een later tijdstip waardoor wijzigingen kunnen worden overschreven.
Maar dan moet de gebruiker weten dat het veld al geüpdatet is en nog belangrijker precies wanneer dat was.

Terwijl het formulier opnieuw ophalen en je wijziging er overheen plakken minder werk is.

👑


Acties:
  • 0 Henk 'm!

  • Cartman!
  • Registratie: April 2000
  • Niet online
http://doctrine-orm.readt...ions-and-concurrency.html

Lees dat eens door, misschien zit daar een oplossing voor je bij :) Als je ook Doctrine ORM gebruikt dan krijg je het min of meer "gratis" erbij al :)

Acties:
  • 0 Henk 'm!

  • TheNephilim
  • Registratie: September 2005
  • Laatst online: 09-10 15:13

TheNephilim

Wtfuzzle

L01 schreef op maandag 20 juni 2016 @ 10:43:
Wat TheNephilim voorstelt is niet helemaal veilig.

De waarde in het hiddenfield kan aangepast worden door de gebruiker naar een later tijdstip waardoor wijzigingen kunnen worden overschreven.
Dat klopt, maar het is uiteraard nog wel te 'beveiligen'. Het ging me meer om het principe dan de daadwerkelijke implementatie. Je zou bijv. ook een sessie waarde kunnen gebruiken, daar kan de gebruiker niet bij.
Pagina: 1