Jump to content
php.lv forumi

Kā pareizāk veidojat db modeļus?


codez

Recommended Posts

  • Replies 35
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

2easy, Tak nav tur nekas kruts, vienkārš piemērs, kuram neredzu pagaidām vienkāršu risinājumu, kurš strādātu 100% pareizi.

2easy, nekoncentrējies tik daudz uz to, lai atrisinātu konkrēto piemēru ar kādu workaroundu, bet gan koncentrējies uz pašu ideju, ka ir nepieciešam realizēt šādu mehānismu:

1)nolasa datus no db

2)php veic aprēķinus

3)saglabā datus db

un izmantojot šo vienkāršo piemēru, pamēģini realizēt šo read->modify->save struktūru tā, lai tā strādātu 100% pareizi.

 

Pagaidām visoptimistiskākais risinājumus, kurš dotu 100% pareizu darbību ir izmantot FOR UPDATE un ķert deadlockus, kuru gadījumā mēģināt realizēt to, lai cikls read->modify->save sāktos no jauna, bet tas nešķiet pagaidām tik vienkārši, jo principā programma jau atrodas pusceļā, kaut kādi mainīgie jau ir inicializēti, kaut kādas struktūras izveidotas un katrā gadījumā smalki pētīt vai atgriežoties sākumā esi pareizi visu reinicializējis ir pasmags darbs, jo vienā aplikācijā šādi read->modify->save cikli ir desmitiem, tāpēc vajag radīt kaut cik universālu un elastīgu šo atgriešanās sākumā mehānismu, ko es tagad arī cenšos izdarīt.

Vai arī atrast citu risinājumu, kā read->modify->save ciklu realizēt 100% pareizi.

Edited by codez
Link to comment
Share on other sites

lieto nevis absolūto set, bet relatīvo increment

UPDATE test12 SET m = m + 100 WHERE id = 1

tad vari kaut vai 10x vienlaicīgus update taisīt un beigās tik un tā būs +1000 :))

 

kkad pasen lasīju, kā šādi iztikt vsp bez lokošanas ;)

 

Ieinteresēja. Vai tiešām šāda darbība tāpat konkrētajā gadījumā izsauc kļūdu un ir nepieciešamas transakcijas?

Link to comment
Share on other sites

vajag radīt kaut cik universālu un elastīgu šo atgriešanās sākumā mehānismu, ko es tagad arī cenšos izdarīt.

Vai arī atrast citu risinājumu, kā read->modify->save ciklu realizēt 100% pareizi.

kad atrodi labu risinājumu, noteikti šeit ieposto ;)

good luck

Edited by 2easy
Link to comment
Share on other sites

Šeit viens no risinājumiem kā apstrādāt deadlockus:

test12.php

test12_ajax.php

 

1)tika izveidots deadlockexceptions

class DeadlockException extends Exception{
}

 

2)db klasē pie kveriju izpildes, ja kverijs neizdevās un kļūda no ir 1213 (deadlock) izmetam DeadlockException

function q($s){
   if (!$res=$this->query($s)) {
     if ($this->errno==1213) {
       $this->deadlocks++;
       throw new DeadlockException('');
     } else {
       die($this->errno.':'.$this->error);
     }      
   }
   return $res;
 }

 

3)Visu transakciju lieka try cahce, kuru savukārt liekam while ciklā, kurš testē vai transakcija veiksmīgi pabeigta.

Parediģējam arī commit metodi, kurā pievienojam, ka veiksmīgas šīs metodes izsaukšanas gadījumā, deadlock nomainam uz false;

Tāpat pie cache notestējam vai nav sasniegts maksimālais deadlocku skaits <- šo gan varētu pārmest testēt DB klasē vietā, kura palielina deadlocku skaitu un attiecīgi deadlock exception izmešanas vietā pie pārsniegta skaita, pārtraukt requestu vispār.

$db->startTransaction();
while ($db->isDeadlock()){
 try {    
   $m1=$db->q1("SELECT m FROM users where id=$fromid FOR UPDATE");
   sleep(1);
   $m2=$db->q1("SELECT m FROM users where id=$toid FOR UPDATE");
   echo "user $fromid: $m1\n";
   echo "user $toid: $m2\n";
   $m1-=1;
   $m2+=1;
   sleep(1);
   $db->query("UPDATE users SET m=$m1 WHERE id=$fromid");
   $db->query("UPDATE users SET m=$m2 WHERE id=$toid");
   $db->commit();
 } catch (DeadlockException $e) {
   if($db->isMaxDeadlocks()) {
     $db->noDeadlocks;
     //šeit attiecīgi izdomājam ko darīt, ja sasniegts maksimālais deadlocku skaits.
     //normālā darbībā šim nevajadzētu izsaukties
   }
 }
}

 

 

 

EDIT:

 

šeit variants, kad max_deadlocks apstrādā pašā DB klasē, to sasniegšanas gadījumā pārtrauc requestu:

test12_ajax.php

 

 

 

Katrā gadījumā, testējot piemēru var redzēt, kā viens no requestiem izpildās 2 sekundēs, bet otrs trijās, jo pēc pirmā sleep nonāk deadlockā un sāk visu transakciju no jauna.

Tāpat arī baigās var redzēt, ka otrajam requestam ir viens deadlocks.

Edited by codez
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

×
×
  • Create New...