Toon posts:

[MySQL] meerdere users op dezelfde tabel: gegevens verloren

Pagina: 1
Acties:
  • 157 views sinds 30-01-2008
  • Reageer

Verwijderd

Topicstarter
hey mensen,

ik heb een online formulier wat door meerdere mensen opgeslagen/aangepast kan worden, nu is het probleem dat wanneer 2 gebruikers dezelfde info wijzigen op hetzelfde moment, gegevens verloren gaan, iemand een idee hoe ik dit oplos?

Verwijderd

Zorgen dat de data in het formulier gelocked is zodra het in gebruik is, als de wijziging is doorgevoert geef je de data weer vrij voor iemand anders om wijzigingen aan te brengen.

  • -=bas=-
  • Registratie: Oktober 2000
  • Laatst online: 22-04-2025
Zoeken met Google? :P

Je moet proberen te voorkomen dat 2 mensen gelijktijdig op dezelfde dataset gaan werken. Lock dus de spullen waar je mee aan de slag wil. Als het al gelocked is dan moet je een melding geven dat je even moet wachten.
De truuk is om slechts die data te locken die relevant is, niet heel je DB locken want dan heb je minder vrolijke gebruikers.
Met Google kan je denk ik wel voldoende voorbeelden vinden.
Jet kan het met MySQL oplossen maar ook gewoon met een eenvoudige PHP var/array kan je al een hoop problemen voorkomen als je een eenvoudige toepassing (met meerdere gebruikers hebt)

Senile! Senile Oekaki


Verwijderd

Topicstarter
ik heb echt al veel gezocht, op veel pagina's zijn er soortgelijke topis, maar bij geen van allen worden ze opgelost :'(

er stond ook iets van LOCK TABLES, maar dit werkt ook niet bij mij =\
<?
$lock="LOCK TABLE klanten";
$unlock="UNLOCK TABLE klanten";
$query = "UPDATE klanten set updatdd='$updatdd', fnaam='$fnaam' ,naam='$naam', adres='$adres' ,postc='$postc' ,plaats='$plaats' ,tel1='$tel1' ,tel2='$tel2' ,
tel3='$tel3' ,instal = '$instal', pakket = '$pakket', login = '$login', adate='$adate' , adatedd='$adatedd', extra='$extra' ,connect='$connect' ,ready='$ready', notitie='$notitie' where ID = $selid";

$result = mysql_query($query);
mysql_free_result;
mysql_query($unlock);
mysql_close;
?>

of ziet een van jullie hier een fout in zitten?

  • Bosmonster
  • Registratie: Juni 2001
  • Laatst online: 10-05 18:53

Bosmonster

*zucht*

http://www.mysql.com/doc/en/LOCK_TABLES.html

Daar staat precies uitgelegd hoe locking werkt in MySQL :)

Verwijderd

Krijg je een SQL-fout? Zo ja, wat is de foutmelding?

Verwijderd

Topicstarter
@ bosmonster: ik heb de documentation al gelezen, hier word ik niet veel wijzer van eerlijk gezegd |:(

@johnnie: nee, ik krijg juist geen sql- foutmelding, dat is juist het rare, het enige is dat ik toch met 2 users tegelijk de gegevens kan benaderen en wijzigen :/

-edit-
bosmonster verkeerd getypt :+
-edit-

[ Voor 9% gewijzigd door Verwijderd op 23-03-2004 16:46 ]


  • ripexx
  • Registratie: Juli 2002
  • Laatst online: 08:59

ripexx

bibs

Je haalt verschillende locking door elkaar. Zodra jij een record, insert, update of verwijderd doet mysql een complete table lock (MyISAM) zodat een andere query niet bij dezelfde records kan.

Waar jij tegen aanloop is het probeel dat je in je applicaties een formulier wil aanpassen, dus zodra je het gaat aanpassen dat iemand anders het niet kan aanpassen. In php/mysql los je dit het eenvoudigste op dmv een eigen locking systeem. Je reserveert dan het recht om aan te passen, de ander krijgt een melding dat persoon x bezig is en het formulier pas na xx:xx tijd weer aan te passen is. Je maakt gewoon een extra datetime veld en een user id veld aan in tabel. Zodra je het gaat aanpassen zet je een nieuwe datum tijd in de db.

//offtopic
InnoDB tabellen onsteunen wel row level locking, zodat er toch meerdere inserts en updates tegelijk op de tabel kunnen worden uitgevoerd

buit is binnen sukkel


  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 21-02 23:50
Verwijderd schreef op 23 maart 2004 @ 16:35:
ik heb echt al veel gezocht, op veel pagina's zijn er soortgelijke topis, maar bij geen van allen worden ze opgelost :'(

er stond ook iets van LOCK TABLES, maar dit werkt ook niet bij mij =\
[..hoop code..]

of ziet een van jullie hier een fout in zitten?
Ja, je voert die $lock en $unlock niet als mysql_queries uit.

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info


Verwijderd

Topicstarter
mja, ik haal ze door elkaar dan denk =\

ik weet alleen dat ik gegevens wil wijzigen, die worden eerst opgevraagd uit de MySQL database(MyISAM) op dat moment moet het dus gelocked worden, voor mijn part heel de tabel, maar de andere gebruikers moeten er niet meer aan kunnen, anders overschrijven we elkaars wijzigingen =)

heb je een beter idee dan?

gr

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 14:50

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op 23 maart 2004 @ 16:20:
hey mensen,

ik heb een online formulier wat door meerdere mensen opgeslagen/aangepast kan worden, nu is het probleem dat wanneer 2 gebruikers dezelfde info wijzigen op hetzelfde moment, gegevens verloren gaan, iemand een idee hoe ik dit oplos?
Hoi, welkom op GoT :)
Ik adviseer je om even P&W FAQ - Het FAQ/Beleid topic door te lezen, en met name P&W FAQ - De "quickstart". Daarin staat wat we van een topicstart verwachten, verwachtingen die absoluut niet voldaan worden met je huidige topicstart :) Verzin ook een wat zinnigere titel, probeer je probleem daarin kort maar krachtig te omschrijven zodat mensen weten wat ze van een topic kunnen verwachten voordat ze erop klikken

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
[b][message=20327157,noline]Grijze Vos schreef op 23 maart 2004 @

Ja, je voert die $lock en $unlock niet als mysql_queries uit.
en wat staat hier dan?
...
mysql_free_result;
mysql_query($unlock);
mysql_close;
...
of doe ik dat ook al verkeerd? :/

Verwijderd

Topicstarter
.oisyn schreef op 23 maart 2004 @ 16:54:


Hoi, welkom op GoT :)
Ik adviseer je om even P&W FAQ - Het FAQ/Beleid topic door te lezen, en met name P&W FAQ - De "quickstart". Daarin staat wat we van een topicstart verwachten, verwachtingen die absoluut niet voldaan worden met je huidige topicstart :) Verzin ook een wat zinnigere titel, probeer je probleem daarin kort maar krachtig te omschrijven zodat mensen weten wat ze van een topic kunnen verwachten voordat ze erop klikken
sorry hoor .oisyn, ik wilde alleen geholpen worden, niet afgezeken ;)
ik zal er aan denken de volgende x

  • ripexx
  • Registratie: Juli 2002
  • Laatst online: 08:59

ripexx

bibs

Verwijderd schreef op 23 maart 2004 @ 16:54:
mja, ik haal ze door elkaar dan denk =\

ik weet alleen dat ik gegevens wil wijzigen, die worden eerst opgevraagd uit de MySQL database(MyISAM) op dat moment moet het dus gelocked worden, voor mijn part heel de tabel, maar de andere gebruikers moeten er niet meer aan kunnen, anders overschrijven we elkaars wijzigingen =)
Wat wil je uiteindelijk bereiken? Als het niet uitmaakt dat een tabel geheel gelocked wordt dan kan je in princiepe de table locks van mysql gebruiken. Wil je zoiets zoals op de t.net frontpage, meerdere mensen kunnen aan hetzelfde artikel werken terwijl de users gewoon nog het nieuws kunnen lezen dan moet je zelf iets maken in PHP. :)

In pseude code als je de gehele tabel wil locken:

PHP:
1
2
3
4
5
6
7
8
// Haal gegevens op
$dataset = mysql_query($select);
// Lock tabel
mysql_query($lock);
// Doe een update
mysql_query($update);
// Unlock
mysql_query($unlock);

[ Voor 14% gewijzigd door ripexx op 23-03-2004 17:03 ]

buit is binnen sukkel


  • Infinitive
  • Registratie: Maart 2001
  • Laatst online: 25-09-2023
Houdt het wijzigen van zo'n formulier soms in dat je meerdere operaties op de database tegelijk loslaat die op zich als 'een' zouden moeten worden gezien? In dat geval zou je eens naar transacties kunnen kijken.

Transacties is zo wie zo een mooier alternatief dan lock tables...

Een simple uitleg over wat een transactie is:
je kan dat je een transactie wilt beginnen. Dan ga je operaties op de database uitvoeren. Selects, inserts, updates, etc. En als je je ding gedaan hebt, dan zeg je tegen de database dat hij deze wijzigingen door moet voeren (commit). Als er anderen zijn die van dezelfde gegevens gebruik willen maken, dan zullen ze - afhankelijk van het concurrency level - in de wacht gezet worden.

[ Voor 46% gewijzigd door Infinitive op 23-03-2004 17:05 ]

putStr $ map (x -> chr $ round $ 21/2 * x^3 - 92 * x^2 + 503/2 * x - 105) [1..4]


Verwijderd

Topicstarter
@ripexx: jah zoiets zou het moeten worden denk ik,

- de informatie uit een tabel halen,
- dan de tabel op slot zodat niemand er iets aan ken veranderen en eventueel een melding krijgt.
je kan de gegevens veranderen,
-dan net nadat de update is uitgevoerd de tabel weer unlocken zodat andere gebruikers weer hun updates kunnen uitvoeren, maar wel de gegevens die net zijn ingevoerd te zien krijgen.

_/-\o_

-edit-
ik heb een tabel, hierin staan orders van klanten.
soms moet er een order bijgezet worden of gewijziigd, dit kan door meerdere gebruikers geschiedden.
wanneer gebruiker1 een order aan het wijzigen is, moet gebruiker2 en eventueel gebruiker3 in feite wachten tot gebruiker1 klaar is en alles geupdate heeft.
DÁN pas kunnen de andere gebruikers toegang krijgen tot de order informatie en die weer kunnen wijzigen.
-edit-

[ Voor 37% gewijzigd door Verwijderd op 23-03-2004 22:34 ]


Verwijderd

Topicstarter
@infinitive: ik begrijp niet helemaal wat je bedoelt, maar ik denk dat hetgeen ripexx hierboven uitlegde, heel dicht in de buurt komt van wat ik wil.

als ik het verkeerd heb, corrigeer me aub. B)

  • Infinitive
  • Registratie: Maart 2001
  • Laatst online: 25-09-2023
@infinitive: ik begrijp niet helemaal wat je bedoelt, maar ik denk dat hetgeen ripexx hierboven uitlegde, heel dicht in de buurt komt van wat ik wil.
Als je wilt voorkomen dat er in de tussentijd geen operaties op die tabel worden uitgevoerd dan is dat op zich goed. Maar eigenlijk is dat een beetje mysql gehack. Ik heb het zelf ook wel gebruikt omdat de mysql versie die ik draaide nog geen transacties kende. BTW: zelfs als je één tabel wilt locken, dan moet je nog steeds: lock tables gebruiken en niet zonder die s. Anders is hij syntactisch niet correct en zou je een query-error moeten krijgen.

Dus voor mysql kan je het probleem oplossen met lock tables, maar dat is niet de manier waarop je dit standaard oplost: dat is namelijk gebruik maken van de transactie functionaliteit van je database management system. Transacties vormen namenlijk een abstractie voor:

- locken van tabellen. Of netter: isolatie. Vooral als je er meerdere hebt dan is het niet fijn om lock tables te gebruiken i.v.m. mogelijk deadlocks. Wanneer je transacties gebruikt dan lost je dbms dat probleem voor je op.

- Terugdraaien van onvoltooide operaties. Of netter: atomaire operaties. Stel je start een transactie, update wat records, voegt wat nieuwe toe, etc. Halverwege crast je computer. Nu heb je de halve database in de war gegooid. Maar geen nood: alle acties in een transactie vormen een geheel: ofwel ze worden allemaal netjes uitgevoerd, of niet: in het laatste geval worden gedane veranderingen automatisch teruggedraaid alsof ze nooit voorgekomen waren.

Maar kijk ook eens naar de reply's van ripexx. Je probleem kan ook in een andere hoek zitten. Bijvoorbeeld omdat dingen gewijzigd worden buiten de lock tables om. Bedenk verder ook dat in geval van een php-script, dat je lock alleen gedurende de uitvoering van dat script geplaatst is. Of totdat je de lock opheft.

[ Voor 5% gewijzigd door Infinitive op 24-03-2004 00:31 ]

putStr $ map (x -> chr $ round $ 21/2 * x^3 - 92 * x^2 + 503/2 * x - 105) [1..4]


Verwijderd

Topicstarter
mja, ik heb het nu met LOCK TABLES gedaan, hier kan je de code bekijken:

http://tnx.nl/2387BMXH

maar dit werkt dus nie, ik open deze pagina, maar iedereen kan nog gewoon dingen wijzigen in de tabel =\

iemand die een fout ziet?

  • SilencerNL
  • Registratie: Juli 2002
  • Laatst online: 14:31

SilencerNL

No remorse

Je locked hem nadat je je query uit hebt gevoerd...

Zoals hierboven al eens is gezegt:

- locken
- query uitvoeren
- unlocken

edit:
Ik zie dat je een lock om je select query probeert te zetten. Naar mijn mening niet nodig. Nu locked hij hem alleen tijdens het laden, dus zodra jij info op het scherm ziet, is de tabel weer unlocked...

Je moet je lock om je update/insert query plaatsen... dat is waarschijnlijk de oplossing voor jou probleem. Dit zorgt ervoor dat de gebruikers niet tegelijk in de tabel schrijven

[ Voor 64% gewijzigd door SilencerNL op 25-03-2004 11:22 ]

Don't dream your life, live your dreams!


Verwijderd

Topicstarter
jah er komt een pagina na deze, daar worden de wijzigingen opgeslagen.
zou ik de unlock daar achter de wuery moeten zetten dan???

  • SilencerNL
  • Registratie: Juli 2002
  • Laatst online: 14:31

SilencerNL

No remorse

Verwijderd schreef op 25 maart 2004 @ 11:23:
jah er komt een pagina na deze, daar worden de wijzigingen opgeslagen.
zou ik de unlock daar achter de wuery moeten zetten dan???
Ja, in die pagina zet je je lock vóór je je query uitvoert, en je unlock ná je query. Maar lock je tabel pas vlak voor je de query uitvoert, anders is de tabel onnodig lang gelocked

[ Voor 14% gewijzigd door SilencerNL op 25-03-2004 11:26 ]

Don't dream your life, live your dreams!


  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 26-05 22:35

Creepy

Tactical Espionage Splatterer

Silencer_NL schreef op 25 maart 2004 @ 11:18:
Je locked hem nadat je je query uit hebt gevoerd...

Zoals hierboven al eens is gezegt:

- locken
- query uitvoeren
- unlocken

edit:
Ik zie dat je een lock om je select query probeert te zetten. Naar mijn mening niet nodig. Nu locked hij hem alleen tijdens het laden, dus zodra jij info op het scherm ziet, is de tabel weer unlocked...

Je moet je lock om je update/insert query plaatsen... dat is waarschijnlijk de oplossing voor jou probleem. Dit zorgt ervoor dat de gebruikers niet tegelijk in de tabel schrijven
De eerste gebruiker opent het scherm om een record te bwerken. Een tweede gebruiker doet nu hetzelfde met hetzelfde record. Daarna schrijft de eerste gebruiker zijn wijzigingen weg (lock -> update -> unlock). Nu doet de tweede gebruiker dat ook. De wijzigingen van de eerste gebruiker zijn nu verloren.

Zonder row-level locking los je dit probleem niet op, tenzij je het niet erg vindt om de gehele tabel te locken als iemand een record gaat bewerken.

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • SilencerNL
  • Registratie: Juli 2002
  • Laatst online: 14:31

SilencerNL

No remorse

Creepy schreef op 25 maart 2004 @ 11:26:
[...]

De eerste gebruiker opent het scherm om een record te bwerken. Een tweede gebruiker doet nu hetzelfde met hetzelfde record. Daarna schrijft de eerste gebruiker zijn wijzigingen weg (lock -> update -> unlock). Nu doet de tweede gebruiker dat ook. De wijzigingen van de eerste gebruiker zijn nu verloren.

Zonder row-level locking los je dit probleem niet op, tenzij je het niet erg vindt om de gehele tabel te locken als iemand een record gaat bewerken.
yep... row-level locking zou hier de beste oplossing zijn ;)

Don't dream your life, live your dreams!


  • Jelmer
  • Registratie: Maart 2000
  • Laatst online: 06:52
De meest eenvoudige manier om dit "lost update" of "dirty write problem" te ondervangen zonder zaken te hoeven locken, is bij het doorvoeren van de update checken of de gegeven nog wel hetzelfde zijn als bij het ophalen ervan.
Voorbeeld:

SELECT x, getal FROM t WHERE id = 1;

Vervolgens wordt getal door een gebruiker aangepast en doe je de volgende update:
UPDATE t SET getal=$getal WHERE id = 1 AND getal=$orig_getal

Als deze query dan geen records update, weet je dat iemand anders je voor is geweest en kun je de gebruiker dit melden.


Daarnaast is het met locking natuurlijk wel zo dat je de gebruiker al vooraf op de hoogte kunt stellen dat iemand aan het editten is.

[ Voor 18% gewijzigd door Jelmer op 25-03-2004 11:31 ]


Verwijderd

Topicstarter
Creepy schreef op 25 maart 2004 @ 11:26:


De eerste gebruiker opent het scherm om een record te bwerken. Een tweede gebruiker doet nu hetzelfde met hetzelfde record. Daarna schrijft de eerste gebruiker zijn wijzigingen weg (lock -> update -> unlock). Nu doet de tweede gebruiker dat ook. De wijzigingen van de eerste gebruiker zijn nu verloren.

Zonder row-level locking los je dit probleem niet op, tenzij je het niet erg vindt om de gehele tabel te locken als iemand een record gaat bewerken.
jah het maakt niet uit of de gehele tabel gelocked is, ik lock de tabel op het moment dat de gegevens geselecteerd zijn, dan als ze geupdate zijn, unlock ik hem weer, dat maakt dan toch niets uit?

en er zijn trouwens maar 3 gebruikers, dus zo erg is het niet als de tabel gelocked is, dan wachten ze maar even he ;)

Verwijderd

Topicstarter
@ Jelmer: `jah maar hoe laat ik dan dat $orig_getal correct checken? :/

en hoe laat je dan checken dat er iemand aan het updaten is?

if TABLE `klanten` LOCKED
echo "Jammer, iemand was je voor";

?????

[ Voor 50% gewijzigd door Verwijderd op 25-03-2004 11:41 ]


  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Het MySQL-commando LOCK TABLES gaat dus niet werken voor je...
LOCK TABLES locks tables for the current thread. UNLOCK TABLES releases any locks held by the current thread. All tables that are locked by the current thread are implicitly unlocked when the thread issues another LOCK TABLES, or when the connection to the server is closed.
Zodra je verbinding sluit (direct nadat je pagina gegenereerd is, meestal) ben je je locks kwijt.
Sowieso is het niet echt de bedoeling dat je maar even alle tabellen lockt om je gegevens op te halen.

Imho kan je het beste per item in je tabel die je wilt kunnen "locken" een soort "mutex" maken, bijvoorbeeld in een aparte tabel.

Vervolgens ga je dan _eerst_ kijken of er al zo'n "mutex" is gepakt door een andere gebruiker, bijvoorbeeld met:
LOCK TABLE mutexes WRITE;
SELECT userid, locktime FROM mutexes WHERE objectid = X;
dat LOCK TABLES zorgt ervoor dat je een write lock op die tabel krijgt en je dus veilig kan updaten in die tabel, zonder dat iemand anders er "net even tussendoor piept" (en je dus twee personen hebt die beiden te zien krijgen dat er geen lock is).

Vervolgens kijk je of de userid gelijk is aan die van de huidige gebruiker, zoja, dan had ie het lock al en kan ie uiteraard gerust verder gaan ;)
De locktime moet je zelf weten of je dat toe wilt voegen, het levert je een controle mechanisme op voor als er ooit een mutex "te lang" blijft bestaan (bijv meer dan een half uur) en je kan die tijd bijwerken als de gebruiker in kwestie dus opnieuw (impliciet) het lock opvroeg.

Mocht er geen mutex zijn voor dat item, dan voer je een mutex in met je insert query en unlock je de tables. Je gebruiker heeft nu een mutex op dat ene item, niemand anders mag er aan komen.
Mocht er dus wel een mutex zijn (die niet van hemzelf is), dan meld je dat aan je gebruiker en eventueel vermeld je erbij wie het lock had en sinds wanneer.

Je moet die mutex al aanmaken zodra iemand het item wil gaan editten (dus een editform opvraagt) en pas weer vrijgeven (deleten) zodra ie dat formulier gesubmit heeft. Die LOCK TABLES mutexes moet je voor elke handeling op die mutexes-tabel doen en zodra je er klaar mee bent weer vrijgeven natuurlijk (UNLOCK TABLES) :)


Je hebt dan dus twee lockingmechanismes (die hier al eerder door elkaar gegooid werden) toegepast, de MySQL-locking om te voorkomen dat er twee queries tegelijkertijd op een tabel worden uitgevoerd en je eigen locking om te voorkomen dat twee gebruikers hetzelfde document gaan editten.

[ Voor 15% gewijzigd door ACM op 25-03-2004 11:51 ]


  • Jelmer
  • Registratie: Maart 2000
  • Laatst online: 06:52
Verwijderd schreef op 25 maart 2004 @ 11:34:
@ Jelmer: `jah maar hoe laat ik dan dat $orig_getal correct checken? :/
Je kunt bijvoorbeeld de originele waarden in een sessie, cookie of hidden formfield zetten en samen met de nieuwe gegevens weer in de query gebruiken.

Verwijderd

Topicstarter
ah kijk, ik ga het even proberen
thx! :)
Pagina: 1