Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> [PHP][Doctrine][MySQL] LOCK i UNLOCK, Strona zawieszona na kilka godzin...
Adi32
post
Post #1





Grupa: Zarejestrowani
Postów: 348
Pomógł: 26
Dołączył: 8.10.2008
Skąd: Lublin

Ostrzeżenie: (0%)
-----


Witajcie.

(temat wisiał niespełna dobę w dziale Forum/Bazy danych/MySQL jednak postanowiłem go przenieść tutaj.
Mimo, że jest to mniej odpowiedni temat to w niewielkim stopniu pasuje a jest tutaj większy ruch).

Teoretycznie wszystkiego mógłbym się dowiedzieć chociażby z manuala, googla itp. ale postanowiłem napisać ponieważ przy aktualnym projekcie potrzebuje mieć pewność co do niektórych rzeczy.

Słowo wstępu.
Przeważnie korzystam z Doctrine ORM. Pojawiła się sytuacja, która zmusza mnie do skorzystania z blokowania tabel (przynajmniej tak mi się wydaje) a to co znalazłem w manualu Doctrina na temat blokowania nic mi nie pomogło, dlatego kod nieco się przeplata.

(1) - Zasada działania blokowania tabel...
Muszę w pewniej tabeli wykonać pewne akcie związane z usunięciem starych rekordów i dodaniem nowych. Ważne jest aby w trakcie wykonywania tych akcji nikt nie mógł nawet czytać z tej tabeli a gdyby jednak próbował to najlepiej jakby jego przeglądarka chwileczkę poczekała na zwolnienie blokady.

w tym celu zaprodukowałem taki kod:

  1. # Blokujemy tabele żeby nikt z niej nie czytał gdy będziemy ją przetwarzać
  2. Library_Baza::getInstance()->query("LOCK TABLES test_acl READ");
  3.  
  4. # kasujemy stare dane
  5. Doctrine_Query::create()->delete("TestAcl")->where("id_uzytkownik = $id")->execute();
  6.  
  7. //pre ($for_save);
  8.  
  9. # dodajemy nowe dane
  10. foreach ($for_save as $save) {
  11. $nowy = new TestAcl;
  12. $nowy->id_uzytkownik = $id;
  13. $nowy->fromArray($save);
  14. $nowy->save();
  15. }
  16.  
  17. # odblokowywujemy tabele
  18. Library_Baza::getInstance()->query("UNLOCK TABLES");


Czy jest on w porządku pod każdym względem? Czy spełnia przynajmniej to zadanie o które mi chodzi?

(2) - Dlaczego wykonanie powyższego kodu (testuje go od 3 dni) daje czasami taki efekt, że:
Dosłownie klikam "zapisz" co powoduje wykonanie się tego kodu i od tej pory przeglądarka czeka na odpowiedź z servera nawet kilka godzin? Można odświeżać, usuwać kod itp - nic nie pomaga. Czy dzieje się tak dlatego, że została zablokowana tabela (z której korzysta każda część skryptu) i cały czas czeka na jej odblokowanie?

(opcjonalnie) - Czy mogę ten efekt uzyskać bez przeplatania? Wykorzystując tylko Doctrine?


Miałem jeszcze jakieś pytania ale wyleciały mi z głowy...
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi
Adi32
post
Post #2





Grupa: Zarejestrowani
Postów: 348
Pomógł: 26
Dołączył: 8.10.2008
Skąd: Lublin

Ostrzeżenie: (0%)
-----


Cytat(Crozin @ 8.06.2012, 10:34:39 ) *
1. Używasz Doctrine w wersji 1.x, może już czas na przesiadkę na 2.2/2.3? O ile dobrze pamiętam nowa wersja wspiera blokowanie tabel - ale to tylko taka mała uwaga.


Korzystałem z Doctrina2 przelotnie (specialnie zaktualizowałem wersję php do nowszej) jednak wykonywanie zapytań było mniej wygodne - spodobała mi sie formuła z Doctrine1. Być może za słabo zapoznałem się z D2?

Cytat(Crozin @ 8.06.2012, 10:34:39 ) *
2. W rzeczy samej, może dojść do jakiegoś deadlocka.

A jak teraz z niego wyjść? W manualu SQL znalazłem różne polecenia i zapytania jednak mam Access Denited przy próbie ich wykonania. Uważam że skoro bez konta roota zrobiłem deadlocka to i powinienem móc go cofnąć...

Cytat(Crozin @ 8.06.2012, 10:34:39 ) *
3. Tutaj w zupełności wystarczy Ci najzwyklejsza transakcja, z poziomu PDO (nie trzeba się nawet bawić w zmianę poziomu izolacji). Co więcej nie ma potrzeby blokowania użytkownika (tabeli). Po prostu odczyta starą zawartość w momencie gdy nowa jest generowana - jest to przecież jedna z czterech podstawowych cech transakcji (ACID).


No faktycznie, masz rację - nie pomyślałem o tym.

Cytat(Crozin @ 8.06.2012, 10:34:39 ) *
4. Czyli ostatecznie (w Doctrine będzie to wyglądało niemal identycznie)
  1. try {
  2. $pdo->beginTransaction();
  3.  
  4. $pdo->query('DELETE ... WHERE user_id = 5;');
  5. $stmt = $pdo->prepare('INSERT ... user_id = 5 ...;');
  6.  
  7. for (...) {
  8. $pdo->execute(array('param1' => 'value', 'param2' => 'value'));
  9. }
  10.  
  11. $pdo->commit();
  12. } catch (...) {
  13. $pdo->rollback();
  14. }
5. Jeżeli użytkownik (user_id#5) wykona zapytanie SELECT, w momencie gdy powyższy kod będzie dopiero na etapie pętli for, zwrócone zostaną wyniki sprzed ustanowienia transakcji, czyli sprzed usunięcia rekordów dot. tego użytkownika.


Dzięki Crozin.
Go to the top of the page
+Quote Post

Posty w temacie


Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 7.10.2025 - 08:05