Avatar billede nemlig Professor
16. april 2013 - 11:01 Der er 11 kommentarer og
1 løsning

Problemer når script kaldes samtidig - kan tabel reserves

Hejsa.
Jeg har et script som har en afviklingstid på 4-5 sekunder.
Der sker følgende:
1. Tjek MySQL, hvornår der sidst er gemt en post.
2. Er der sidst gemt for mere end 10 minutter siden, så hent nogle målerværdier fra ekstern site. Denne del tager ca. 4-5 sekunder
3. Skriv værdierne ned i tabellen.

Mit problem er, at mit script kan blive kaldt flere gange inden for afviklingstiden på 4-5 sekunder, og så afvikles punkt 2 og 3 dobbelt eller 3-dobbelt.

Er det muligt under punkt 1, at "reservere" tabellen og frigive den igen under punkt 3.

Min forespørgsel under punkt 1, ser sådan her ud:

if ($stmt = $mysqli->prepare('SELECT COUNT(*) as `antal` FROM `maalere` WHERE DATE_ADD(`datetime`, INTERVAL 10 MINUTE) >= NOW() AND `server` = ?')) {

Jeg bruger PHP og er blevet inspireret af oleboles guide til MySQLi. Scriptet ligger på et alm. webhotel, Wannafind.
Avatar billede erikjacobsen Ekspert
16. april 2013 - 11:07 #1
Det lyder som en mulighed at låse tabellen i de 4-5 sekunder. Kommer der een opdatering mere i perioden vil den så blot vente.

http://dev.mysql.com/doc/refman/5.0/en/lock-tables.html
Avatar billede nemlig Professor
16. april 2013 - 11:16 #2
Interessant, men er det INSERT INTO, der blot venter eller er det også min SELECT under punkt 1.
Løsningen skal gerne være, at SELECT også afventer opdateringen af den første programafvikling, således SELECT i 2. kørsel fanger, at der lige er gemt en post.
Avatar billede erikjacobsen Ekspert
16. april 2013 - 12:07 #3
Hvis du siger

  LOCK TABLES dintabel WRITE;

så er der låst for både INSERT og SELECT.

Man skal normalt ikke bruge LOCK TABLES, men jeg synes at kunne læse, at du har et par processer, der kommer regelmæssigt, men kan risikere at ramme oven i hinanden. Så går det nok.

Jeg er ret sikker på at Facebook ikke låser tabellerne, når der kommer een opdatering ...
Avatar billede nemlig Professor
16. april 2013 - 18:34 #4
Tak for din gode tips.
Jeg kan jo også vælge, at lave et trin 2½, hvor jeg laver samme tjek som i trin1, da dette kald tager millisekunder.

Men jeg har lige et spørgsmål til trin3, som måske også kan løse det.

Når jeg skriver til tabellen med INSERT INTO, kan jeg så på en eller anden måde få "WHERE DATE_ADD(`datetime`, INTERVAL 10 MINUTE) >= NOW()" med, så der kun indsættes, hvis sidste post er mere end 10 minutter gammelt?
Avatar billede erikjacobsen Ekspert
16. april 2013 - 19:43 #5
Nej, det kan man ikke.

Men der er da andre muligheder.

1) Den simple - sørge for at der kun kaldes hvert 10. minut - fx via et cronjob, sat op til netop dette.

2) I stedet for at låse hele tabellen, så køre det i en transaktion, som kun vil låse relevante rækker.
Avatar billede kjulius Novice
20. april 2013 - 13:12 #6
Et par betragtninger fra sidelinjen:

Umiddelbart lyder en write låsning af tabellen som en udmærket ide til at sikre, at andre sessions ikke kan ændre i tabellen i fremfindings-tidsrummet.

Men det vil også betyde, at tabellen samtidig ikke kan læses til andre formål. Jeg ved selvfølgelig ikke, om det er relevant, men det kunne jo være, at du f.eks. havde en side, hvor du godt ville kunne vise indholdet af tabellen selv om der var en insert undervejs.

Et forslag kunne være at indføre en slags semafor tabel med 1 row og 1 boolean felt, hvor man opdaterer med opdateringsstatus. Denne opdateringsstatus skal så tjekkes for at se, om andre sessioner allerede er i gang med at opdatere/tilføje målinger. Det vil så betyde, at forløbet skal ændres lidt:

1) SELECT mus.updating FROM maalerupdatestatus mus WHERE mus.updating=0 AND NOT EXISTS (SELECT * FROM maalere WHERE DATE_ADD(datetime, INTERVAL 10 MINUTE) >= NOW() AND server = ?)
2) Hvis selecten returnerer en record/row, så skal der:
2a) UPDATE maalerupdatestatus SET updating = 1
2b) Hent ny måling
2c) INSERT INTO maalere
2d) UPDATE maalerupdatestatus SET updating = 0

Indrømmet, der er flere steps og umiddelbart vil det måske synes lidt omstændeligt, men det har også sine fordele.

Du har i din select også et kriterie på et felt der hedder server. Hvis det betyder, at der kan være flere servere der skal hentes data fra, så skal du nok også have det samme felt inkluderet i semafor-tabellen og så have en row for hver server i denne. Det vi så også ændre ovenstående lidt:

1) SELECT mus.updating FROM maalerupdatestatus mus WHERE mus.updating=0 AND server = ? AND NOT EXISTS (SELECT * FROM maalere WHERE DATE_ADD(datetime, INTERVAL 10 MINUTE) >= NOW() AND server = mus.server)
2) Hvis selecten returnerer en record/row, så skal der:
2a) UPDATE maalerupdatestatus SET updating = 1 WHERE server = ?
2b) Hent ny måling
2c) INSERT INTO maalere ....
2d) UPDATE maalerupdatestatus SET updating = 0 WHERE server = ?


Vær også opmærksom på, at hvis der sker et nedbrud mellem punkt 2a og 2d, vil det kunne forhindre yderligere indsætning. Den risiko vil dog kunne elimineres ved at køre punkterne 2a - 2d som en transaktion, således at ændringer maalerupdatestatus mv. bliver rullet tilbage ved fejl.

Disclaimer: Jeg har ikke testet noget af dette. Det er alene tanker som du selv kan arbejde videre med. Mit kendskab til mySQL er desuden begrænset, så der kan sagtens være ting jeg overser.
Avatar billede erikjacobsen Ekspert
20. april 2013 - 13:18 #7
Der er ingen grund til at genopfinde en semafor, når MySql har indbygget en sådan. Så man kunne bruge

  http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_get-lock

hvis det ellers giver mening i sammenhængen, naturligvis.
Avatar billede kjulius Novice
20. april 2013 - 14:33 #8
Interessant. :-)

Ja, det ville jo i hvert fald være at udnytte en indbygget funktionalitet og eliminere behovet for en ekstra tabel.
Avatar billede arne_v Ekspert
21. april 2013 - 02:13 #9
Re #6)

Hvis ikke SELECT er i samme transaktion som resten og transaction isolation level >= repeatable read og InnoDB tabel, saa blokerer den logik ikke noedvendigvis for samtidige opdateringer.
Avatar billede arne_v Ekspert
30. juli 2013 - 05:07 #10
Tid at faa afsluttet her?
Avatar billede nemlig Professor
31. juli 2013 - 21:23 #11
Sorry - den var smuttet.

Jeg løste det ved en punkt 2,5, hvor jeg lige ind jeg skriver til tabellen tjekker igen, om der er skrevet. Så er jeg ikke løbet i problemer siden.

Smid venligst et svar, jer der har bidraget med forslag.
Så deler jeg pointene.
Avatar billede arne_v Ekspert
01. august 2013 - 05:44 #12
svar fra mig
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Computerworld tilbyder specialiserede kurser i database-management

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester