Avatar billede ferrari_brian Nybegynder
16. august 2006 - 14:40 Der er 15 kommentarer og
1 løsning

forhindre 2 i at læse det samme (semaphore)

Hej

Jeg har en C++ applikation der kører og tjekker i databasen, den ser om der er noget scheduleret i en tabel. Men jeg vil gerne have dette program til at køre på flere maskiner samtidig, som læser op mod den samme database. Jeg har alt forbindelse klar og den kan også sagtens gøre det, men jeg har ikke haft applikationerne til at køre samtidig på 2 maskiner, for de må IKKE tage den samme "task" fra min scheduled tabel.

Det vil sige at når applikationen har læst at der er noget der skal laves, ændrer den state fra 0 til Started. Og derefter vil ingen af de andre maskiner tage samme task, medmindre state bliver sat til 0 igen (state kan også være lig "Force", men det betyder ikke så meget i denne sammenhæng). Det jeg så vil høre om der er nogen der har lavet eller ved hvordan man laver således at der bliver lavet en slags semaphore-styring, således at 2 maskiner ikke kan læse i databasen samtidig eller helst ikke i den samme tabel samtidig? således at 2 maskiner ikke kan begynde den samme task.

Jeg vil helst ikke at de skal kommunikere internt, da der kan være fra 1-xx maskiner der skal kunne læse her, derfor ville det være godt hvis tabellen "låste" når der var en applikation der prøvede at få fat i den...

Jeg er lidt ny i MySQL, så bær lige over med mig... Især hvis funktion er lige til og allerede lavet.

på forhånd tak for hjælpen... :)

/Brian
Avatar billede arne_v Ekspert
16. august 2006 - 15:55 #1
jeg mener at det er bedst at loese det i MySQL fremfor i C++

hvis du bruger InnoDB saa bruger du bare transaktioner og et passende hoejt transaction
isolation level

hvis du bruger MyISAM saa maa du vist bruge LOCK table til det
Avatar billede arne_v Ekspert
16. august 2006 - 16:00 #2
for noget generel baggrund er http://www.eksperten.dk/artikler/996 maaske interessant
Avatar billede ferrari_brian Nybegynder
17. august 2006 - 09:44 #3
Hej

Tak for svaret... men nu er det sådan at jeg på den maskine jeg udvikler det på bruger InnoDB, men jeg er ret sikker på at der vil ligge MyISAM på maskinen når den bliver lagt på nettet... (det er en linux-maskine)

Hvad skal man så?
Avatar billede ferrari_brian Nybegynder
17. august 2006 - 09:49 #4
jeg går igang med at læse din artikel ... jeg kan se du skriver om tingene... men jeg ved ikke lige hvilken løsning der egner sig, da jeg gerne vil lave en generel løsning, hvis det senere skal flyttes.
Avatar billede ferrari_brian Nybegynder
17. august 2006 - 09:50 #5
jeg ved godt det er en C++ applikation, og at den ikke ligger på nettet, men det gør databasen, som får data udefra, og deri læser C++ appliktaionen...
Avatar billede ferrari_brian Nybegynder
17. august 2006 - 17:06 #6
Jeg har nu lavet det med LOCK TABLES ... og dette betyder ikke så meget, for det er kun 1 sted i alle applikationer hvor det er nødvendigt, fordi at de ikke skal starte samme task. Derefter er en af felterne sat fra 0 til started, og den kan dermed ikke "tages" mere.

Tak for hjælpen. Jeg har dog ikke testet det på MyISAM systemet, men det virker fint på min egen InnoDB

mysql_query("LOCK TABLES table_name WRITE;");
mysql_query("SELECT * FROM table_name WHERE field_name = '0'");
mysql_query("UPDATE table_name SET field_name = 'started' WHERE Id = id_from_select_query");
mysql_query("UNLOCK TABLES;");

Det skal lige siges at det er meget vigtigt at huske ; i LOCK TABLES queries, ellers virker det ikke :)
Avatar billede arne_v Ekspert
18. august 2006 - 02:33 #7
LOCK virker også fint på MyISAM.

På InnoDB er det lidt at plante tulipaner med en bulldozer, men det virker.
Avatar billede ferrari_brian Nybegynder
18. august 2006 - 08:29 #8
Ja jeg ved det godt, for jeg kunne godt se meningen med det andet. Dog er det så kort tid at den låser tabellen at det ikke vil have noget at sige. Det eneste den gør er at låse tabellen, derefter lavet et select-kald og så opdatere 1 felt og så låse op igen.

Kaldet er ens hver eneste gang, med de samme krav, så det vil ikke gå galt.

Mange tak for hjælpen.
Avatar billede Slettet bruger
20. august 2006 - 22:59 #9
En anden mulighed kunne være at lave en ny tabel med oplysning om hvem, der "har" den pågældende task. Denne tabel skal så have samme primærnøgle som din nuværende tabel.

Når dit program så vil tage en task, skal den først lave en INSERT i stil med:

  INSERT INTO taskowner (id, owner) VALUES (taskid, processid)

Hvis denne INSERT giver affected rows=1, så var den taks ikke taget, ellers skal programmet vælge en anden task.
Avatar billede Slettet bruger
20. august 2006 - 23:00 #10
Til den simple brug, jeg har nævnt her, er det forresten ikke engang nødvendigt med owner-kolonnen i den ny tabel.
Avatar billede ferrari_brian Nybegynder
21. august 2006 - 08:25 #11
Jeg tror måske at det er mere sikkert at bruge LOCK TABLES, for der kan de ikke komme til at læse og skrive samtidig, og derfor kan de ikke fx lave samme insert kommando samtidig...

eller ? ... Jeg har valgt at bruge LOCK TABLES.
Avatar billede Slettet bruger
21. august 2006 - 11:15 #12
Ja det virker også at låse en tabel, det var mere for at gøre opmærksom på den anden mulighed.

Og det kan ikke lade sig gøre, at to kommer til at lave samme INSERT, da de så vil have samme primærnøgle, og det forhindrer MySQL (Den giver en DUPLICATE KEY fejl for den, der kommer som nummer to).
Avatar billede ferrari_brian Nybegynder
21. august 2006 - 11:53 #13
Det er rigtigt... medmindre den har auto_increment på ... men hva... det andet virker fint!
Avatar billede arne_v Ekspert
22. august 2006 - 02:16 #14
eksemplet ligner faktisk long time pessimistic locking i min artikel lidt

det virker fint

største problem er nok oprydnings problemet

rigtige locks er hængt op på connection og timer ud hvis der skulle ske
noget med applikationen
Avatar billede ferrari_brian Nybegynder
28. august 2006 - 15:12 #15
skal vi lukke ?
Avatar billede arne_v Ekspert
28. august 2006 - 15:16 #16
var det en opfordring til et svar ?
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