Forum Indeks
Forum for E-skakklubben
 
 FAQFAQ   SøgSøg   Tilmeldte brugereTilmeldte brugere   GrupperGrupper   TilmeldTilmeld 
 ProfilProfil   Login for at vise private beskederLogin for at vise private beskeder   LoginLogin 

Flere mysql-kald

 
Skriv nyt emne   Besvar indlægget     Forum Indeks -> Programmeringsmæssigt
Vis foregående emne :: Vis næste emne  
Forfatter Besked
Brian Lundgaard
Site Admin


Indmeldt: 01. nov 2004
Indlæg: 869

IndlægSkrevet: Ons nov 24, 2004 10:20    Emne: Flere mysql-kald Besvar, med citat

Jeg er bange for, at trækregistreringen er utilstrækkelig. I øjeblikket foregår det således:

Jeg henter aktuelt antal træk (før det som udføres nu) med SQL-kald (select where id=traek)

Så lægger jeg en til (++$traek_antal;)

Så skriver jeg det nye antal træk til databasen (update where id=traek)

Problemet er, at jeg er komplet sikker på, at det ind i mellem sker, at flere brugere udfører træk samtidig, hvorfor de henter samme trækantal fra databasen, begge lægger een til og efter tur skriver samme nye trækantal (fx 944.444) tilbage. Det er ikke mange gange om dagen, men jeg ville jo gerne have det helt rigtigt!

Nu ved jeg, at det er muligt at opdatere et tal (lægge een til) i databasen uden at læse det først. Problemet er jo, at jeg har brug for begge dele - jeg skal både lægge en til OG vide, hvad det nye tal er! Kan det gøres i et kald til databasen?
Tilbage til toppen
Vis brugerens profil Send privat besked Send email Besøg brugerens webside
bk



Indmeldt: 03. nov 2004
Indlæg: 290

IndlægSkrevet: Fre nov 26, 2004 14:38    Emne: Brug en AUTO_INCREMENT kolonne Besvar, med citat

Jeg går ud fra, at du i virkeligheden har brug for at være sikker på, at to træk ikke får det samme ID-nummer. Der findes forskellige metoder for at sikre dette, men i MySQL er den mest almindelige at bruge en AUTO_INCREMENT kolonne.

Hvis du fx har en tabel, der er defineret således:

Kode:
CREATE TABLE move (
    move_id INT NOT NULL AUTO_INCREMENT,
    game_id INT NOT NULL,
    move_num INT NOT NULL,
    is_white_move BOOLEAN NOT NULL,
    PRIMARY KEY (move_id)
);


så vil du sætte trækket ind på denne måde:

Kode:
mysql_query("INSERT INTO move (game_id, move_num, is_white_move) ($parti, $traeknummer, $er_hvidt_traek)");


og finde ud af hvilket move_id trækket fik ved umiddelbart bagefter at gøre

Kode:
$move_id = mysql_insert_id();


Hvis man gør det på denne måde er der ingen risiko for, at to træk får det samme ID-nummer, selv om der skulle være to spillere, der udfører sit træk samtidigt.
_________________
- Baldur
Tilbage til toppen
Vis brugerens profil Send privat besked
Brian Lundgaard
Site Admin


Indmeldt: 01. nov 2004
Indlæg: 869

IndlægSkrevet: Fre nov 26, 2004 14:48    Emne: Besvar, med citat

Jeg har faktisk en hel tabel, som hedder statistik. I den er der en kolonne med ID "traek". Den har kun een anden værdi, nemlig det aktuelle trækantal. Så kører jeg:

Kode:
$resultat = mysql_query("SELECT value FROM statistik WHERE id='traek' LIMIT 0,1");

while ($raekke = mysql_fetch_array($resultat)) { extract($raekke); }

$naeste=$value+1;

$query = mysql_query("update statistik set value='$naeste' WHERE ID like 'traek'");


Kan det bygges smartere op?
Tilbage til toppen
Vis brugerens profil Send privat besked Send email Besøg brugerens webside
bk



Indmeldt: 03. nov 2004
Indlæg: 290

IndlægSkrevet: Fre nov 26, 2004 16:21    Emne: Besvar, med citat

Oplysingerne på statistik-siden passer ikke så godt til en almindelig relationel tabel-struktur, så det er svært at rådgive om strukturen af statistik-tabellen. Den opbygning, du vælger, er sikkert i orden.

Problemet, som du har med at gøre, burde i virkeligheden løses vha. transactions. Desværre er det usandsynligt, at den opsætning af MySQL, du har adgang til, understøtter dem. Check om din opsætning understøtter InnoDB tabeltypen. Hvis den gør, så starter du en transaction med "begin transaction" i den ene proces, henter og opdaterer oplysningerne, og kalder derefter på "commit". Den anden proces (hvis der er én) venter imens på at kunne komme til. Du kan læse mere om tranaktioner i MySQL her: http://dev.mysql.com/doc/mysql/en/Transactional_Commands.html og om InnoDB her: http://dev.mysql.com/doc/mysql/en/InnoDB.html. For at bruge InnoDB skal du definere (CREATE TABLE) den pågældende tabel med "TYPE=InnoDB". Hvis din opsætning understøtter det, er det den nemmeste og bedste løsning.

Hvis ikke, er du nødt til at lave et hjemmebrygget locking-system, der er adskilt fra databasen og bruge det til at afgøre, hvornår operationen kan udføres. Det mest naturlige er at bruge filsystemet. Fx:

Kode:
$fil_pointer = fopen($lockfile, "w+");
flock($fil_pointer, LOCK_EX);
# database-kode her!
flock($fil_pointer, LOCK_UN);
fclose($lockfile);


Hvis andre processer kommer til, mens en proces har låst en fil på denne måde, venter de på linje 2 indtil den første proces kommer til linje 4. Hvis du kun opdaterer statistik tabellen på denne ene php-side og kun mellem de to flock()-kald, så er der ingen risiko for konflikter.
_________________
- Baldur
Tilbage til toppen
Vis brugerens profil Send privat besked
Brian Lundgaard
Site Admin


Indmeldt: 01. nov 2004
Indlæg: 869

IndlægSkrevet: Søn nov 28, 2004 8:17    Emne: Besvar, med citat

Fint - det prøver vi med nu! Dog har der sneget sig en lille fejl ind:

Kode:
fclose($lockfile);


skal være

Kode:
fclose($fil_pointer);
Tilbage til toppen
Vis brugerens profil Send privat besked Send email Besøg brugerens webside
Vis ikke emner ældre end:   
Skriv nyt emne   Besvar indlægget     Forum Indeks -> Programmeringsmæssigt Alle tidspunkter er GMT + 1 (CET/Europa)
Side 1 af 1

 
Gå til:  
Du kan ikke skrive nye indlæg i dette forum
Du kan ikke besvare indlæg i dette forum
Du kan ikke rette dine indlæg i dette forum
Du kan ikke slette dine indlæg i dette forum
Du kan ikke stemme på afstemninger i dette forum


Powered by phpBB © 2001, 2005 phpBB Group