[mysql] update timestamp tijdens select limit 1

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • scubapro
  • Registratie: September 2000
  • Laatst online: 21-11-2022
Ik heb een db met x.xxx.xxx records. Ieder record heeft een timestamp. Ik voer 2 queries achter elkaar uit.

SELECT * FROM tabel ORDER BY timestamp ASC LIMIT 1

Ik krijg dus de oudste record terug. Daarna doe ik

UPDATE tabel SET timestamp = CURRENT_TIMESTAMP WHERE id = id_van_select

Nu wordt het script zo snel achter elkaar uitgevoerd dat er meerdere keren hetzelfde record geselecteerd wordt. Dus voordat de update query verwerkt is wordt de select meerdere keren uitgevoerd.

Hoe kan ik voorkomen dat er meerdere keren hetzelfde record geselecteerd wordt. Ik zoek dus eigenlijk een update van de timestamp tijdens de select of iets wat het record tijdelijk locked.

Je bent pas echt lui als je het gemak niet zoekt.


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 15-10 22:15

Janoz

Moderator Devschuur®

!litemod

Transacties, eventueel met pessimistic locking. Je zou echter ook kunnen kijken of je je aanroepende proces slimmer kunt maken zodat hij niet als een dolle probeert hetzelfde record te verwerken.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
Waarom 2 queries? Waarom niet gewoon het in 1 stoppen? Dan heb je 99% van het probleem niet meer.

Acties:
  • 0 Henk 'm!

  • GlowMouse
  • Registratie: November 2002
  • Niet online
Gomez12 schreef op vrijdag 06 februari 2015 @ 16:26:
Waarom 2 queries? Waarom niet gewoon het in 1 stoppen? Dan heb je 99% van het probleem niet meer.
Dit. Als het voor een queue is, kun je het geüpdatete record achterhalen mbv een extra variabele of LAST_INSERT_ID(): http://stackoverflow.com/...last-updated-row-in-mysql

Acties:
  • 0 Henk 'm!

  • scubapro
  • Registratie: September 2000
  • Laatst online: 21-11-2022
GlowMouse schreef op vrijdag 06 februari 2015 @ 16:29:
[...]

Dit. Als het voor een queue is, kun je het geüpdatete record achterhalen mbv een extra variabele of LAST_INSERT_ID(): http://stackoverflow.com/...last-updated-row-in-mysql
Ik zou het best in 1 query willen stoppen maar hoe kun je in een select query een update van de timestamp verwerken? De eerste query is een select. Geen insert of update.

Omdat het php script vanaf verschillende kanten aangeroepen wordt kan ik in php niets regelen. Het moet in MySQL. Vandaar de timestamp. Maar het probleem ontstaat dus wanneer er voor de update van de timestamp door request 1 een select gestart wordt door request 2 (of 3, 4 enz)

De queries voer ik al direct achter elkaar uit.

Je bent pas echt lui als je het gemak niet zoekt.


Acties:
  • 0 Henk 'm!

  • GlowMouse
  • Registratie: November 2002
  • Niet online
scubapro schreef op vrijdag 06 februari 2015 @ 19:01:
[...]


Ik zou het best in 1 query willen stoppen maar hoe kun je in een select query een update van de timestamp verwerken? De eerste query is een select. Geen insert of update.
Je kunt je UPDATE een ORDER BY en een LIMIT meegeven. Daarmee update je de juiste rij zonder eerst een SELECT uit te voeren. Daarna heb je nog een extra query nodig als je wilt weten welke rij je hebt geüpdatet.
De queries voer ik al direct achter elkaar uit.
'Direct achter elkaar' is blijkbaar niet snel genoeg, omdat een ander proces tussentijds hetzelfde record kan selecteren. De beste oplossing hiervoor is de UPDATE-query te wijzigen. Transacties werken ook, maar als je die kunt vermijden is dat alleen maar mooi meegenomen omdat je met transacties weer goed moet uitkijken voor andere problemen.

Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Die select kun je toch omschrijven in de update? update ondersteund ook order by en limit 1
Het goede voorbeeld lijkt mij http://stackoverflow.com/a/9932809 en dan ipv where doe je ORDER BY timestamp ASC LIMIT 1

(te laat, dubbel)

Ik vraag me trouwens af welk probleem je aan het oplossen bent, en of daar geen betere oplossing voor is dan een bepaalde tabel steeds updaten. Bijvoorbeeld een tellertje atomisch laten oplopen en id = (tellertje mod [aantal ids]) selecteren.

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • cariolive23
  • Registratie: Januari 2007
  • Laatst online: 18-10-2024
Gebruik een transactie, wat toch al een goed gebruik is, en vervolgens een SELECT ... FOR UPDATE om het gevonden record te locken.

Acties:
  • 0 Henk 'm!

  • scubapro
  • Registratie: September 2000
  • Laatst online: 21-11-2022
Bedankt. Ik heb het opgelost met een query als:

SET @naam := '';
UPDATE tabel SET timestamp = CURRENT_TIMESTAMP, naam = (SELECT @naam := naam)
ORDER BY laatste_controle ASC LIMIT 1;
SELECT @naam;

Hij is niet heel snel. Duurt gem rond de 3 seconden maar er worden geen dubbele records meer gebruikt.

Je bent pas echt lui als je het gemak niet zoekt.


Acties:
  • 0 Henk 'm!

  • GlowMouse
  • Registratie: November 2002
  • Niet online
scubapro schreef op maandag 09 februari 2015 @ 13:50:
Bedankt. Ik heb het opgelost met een query als:

SET @naam := '';
UPDATE tabel SET timestamp = CURRENT_TIMESTAMP, naam = (SELECT @naam := naam)
ORDER BY laatste_controle ASC LIMIT 1;
SELECT @naam;

Hij is niet heel snel. Duurt gem rond de 3 seconden maar er worden geen dubbele records meer gebruikt.
Het zou veel sneller kunnen met InnoDb (als concurrenty een probleem is) en een index op laatste_controle.
Pagina: 1