Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Obsługa transakcji przez PHP
Forum PHP.pl > Forum > PHP
ktuvok
Mam skrypt o następującej konstrukcji:
  1. <?php
  2.  
  3. $SQL1 = &#092;"INSERT INTO ...\";
  4. $SQL2 = &#092;"UPDATE ...\";
  5. $SQL3 = &#092;"UPDATE ...\";
  6.  
  7. $Zacznij = mysql_query(&#092;"BEGIN;\");
  8. $Operacja1 = mysql_query($SQL1);
  9. $Operacja2 = mysql_query($SQL2);
  10. $Operacja3 = mysql_query($SQL3);
  11.  
  12. if (!mysql_error())
  13. {
  14. //Nie ma błędu, zatwierdzam transakcję
  15. $Wykonaj = mysql_query(&#092;"COMMIT;\");
  16. }
  17. else
  18. {
  19. $TrescBledu = mysql_error();
  20. //Wystąpił błąd bazy MySQL:
  21. $Wykonaj = mysql_query(&#092;"ROLLBACK;\");
  22. echo &#092;"Wystąpił następujący błąd bazy danych: $TrescBledu\";
  23. }
  24.  
  25. ?>

Czy taka konstrukcja jest poprawna?

Chodzi mi o to, czy jeśli błąd wystąpi na etapie Operacji1, a Operacja2 i
Operacja3 się powiodą, to czy mysql_error() również zwróci kod błędu?

Ewentualnie - jak inaczej to oprogramować?

I druga rzecz... Transakcja jest traktowana przez bazę w kontekście aktualnego identyfikatora połączenia z bazą, prawda? Ale którego? Każdy mój juzer łączy się z bazą z użyciem (z punktu widzenia bazy) tego samego loginu i hasła. W rezultacie zapytanie o CONNECTION_ID() daje za każdym razem inny rezultat, ale:
  1. <?php
  2.  
  3. $connection = mysql_connect(&#092;"host\", \"juzer\", \"hasło\");
  4.  
  5. ?>

zwraca mi w każdym przypadku Resource id #2 - dlaczego? Czy mogę w ten sposób bezpiecznie używać transakcji, nie martwiąc się, ze jeden juzer wycofa transakcję drugiego?

Pozdrawiam,
K
nospor
Czy wystąpił błąd sprawdzaj po każdej operacji i jeśli jest to wtedy rollback, a nie jak u ciebie sprawdzasz na koniec. To bez sensu
Kinool
nawiazanie polaczenie poprzez wywolanie skryptu twozy inny identyfikator polaczenia pomimo ze uzywasz tych samych danych do polaczenia, jedynie jesli w skrypcie po raz kolejny bedziesz chcial nawiazac polaczenie a wczesniej nie zostanie ono zamkniete to manual mowi wyraznie:
Cytat
Przy drugim wywołaniu mysql_connect() z tymi samymi argumentami, nie będzie nawiązywane nowe połączenie, lecz zwrócony zostanie identyfikator już otwartego połączenia. Argument


co do obslugi sesji ja stosuje cos takiego:

wynik kazdego zapytania dodaje do tablicy np.
  1. <?php
  2. $queries[] = $sql->query('INSERT ...');
  3. ?>

jesli gdzies wynikl blad to w tablicy bedzie gdzies false

potem przed zaakceptowaniem trasakcji daje do sprawdzenie czy w tablicy jest false:
  1. <?php
  2.  
  3. if(in_array(false, $queries))
  4. {
  5.  $sql->query('ROLLBACK'); // gdzies wysapil blad wiec wycofujemy
  6. } else {
  7.  $sql->query('COMMIT'); // nie bylo bledu wiec akceptujemy
  8. }
  9.  
  10. ?>

moze robie to zle ale tak soie to wykombinowalem i z tego co sprawdzalem to dziala poprawnie
ktuvok
Czy wystarczy zatem zrobić to tak:
  1. <?php
  2.  
  3. if (!$Operacja1 OR !$Operacja2 OR !$Operacja3)
  4. {
  5.     //Nie ma błędu, zatwierdzam transakcję
  6.     $Wykonaj = mysql_query(&#092;"COMMIT;\");
  7. }
  8. else
  9. {
  10.     //Wystąpił błąd bazy MySQL:
  11.     $Wykonaj = mysql_query(&#092;"ROLLBACK;\");
  12.     echo &#092;"Wystąpił błąd bazy danych.\";
  13. }
  14.  
  15. ?>
?

@Kinnol:
A czy nie ma znaczenia, że zmienna $connection zwraca mi za każdym razem Resource id #2?

Dziękuję i pozdrawiam,
K
nospor
ale jaki jest sens wykonywać operację 2 i 3 i obciązać serwer skoro operacja 1 się nie powiodła
ktuvok
OK, przerobiłem obsługę błędu na bardziej sensowną i działa.

Ale chciałbym jeszcze wiedzieć, czy mogę bezpiecznie używać transakcji, skoro identyfikator połączenia zwracany mi przez mysql_connect() jest zawsze równy Resource id #2. Czy transakcja odbywa się w ramach tego właśnie identyfikatora, czy w ramach CONNECTION_ID() zwracanego przez MySQL? TO zasadnicza różnica...

Czy ktoś ma na ten temat miarodajne dane?

Pozdrawiam,
K
SongoQ
Podobnie twierdze jak @nospor nie ma sesnu przetwazac dalej zapytan jesli ktoros z wczesniejszych zapytan nie powiodlo sie. Dlaczego? - Nieoptymalne dla bazy i dla serwera www, a po 2 to tak jak bys wykonywal cos co naprawde jest Ci nie potrzebne.
ktuvok
OK, czyli jakoś tak to będzie:
  1. <?php
  2.  
  3. $SQL1 = &#092;"INSERT INTO ...\";
  4. $SQL2 = &#092;"UPDATE ...\";
  5. $SQL3 = &#092;"UPDATE ...\";
  6.  
  7. $Zacznij = mysql_query(&#092;"BEGIN;\");
  8. if(!$Zacznij)
  9. {
  10.  $BledyBazy[] = mysql_error();
  11. }
  12. if(!$BledyBazy)
  13. {
  14.  $Operacja1 = mysql_query($SQL1);
  15.  if(!$Operacja1)
  16.  {
  17. $BledyBazy[] = mysql_error();
  18.  }
  19. }
  20. if(!$BledyBazy)
  21. {
  22.  $Operacja2 = mysql_query($SQL2);
  23.  if(!$Operacja2)
  24.  {
  25. $BledyBazy[] = mysql_error();
  26.  }
  27. }
  28. if(!$BledyBazy)
  29. {
  30.  $Operacja3 = mysql_query($SQL3);
  31.  if(!$Operacja3)
  32.  {
  33. $BledyBazy[] = mysql_error();
  34.  }
  35. }
  36. if (!$BledyBazy)
  37. {
  38. //Nie ma błędu, zatwierdzam transakcję
  39. $Wykonaj = mysql_query(&#092;"COMMIT;\");
  40. }
  41. else
  42. {
  43. //Wystąpił błąd bazy MySQL:
  44. $Wykonaj = mysql_query(&#092;"ROLLBACK;\");
  45. echo &#092;"Wystąpił następujący błąd bazy danych:\";
  46. foreach($BledyBazy as $key=>$BledyBazy)
  47. {
  48. echo &#092;"<BR>$BledyBazy\";
  49. }
  50. }
  51.  
  52. ?>

Chyba, że da się jakoś prościej... Ma ktoś pomysł?


A co z moim (nieszczęsnym) pytaniem nr 2?
SongoQ
Odnosnie kodu no to cos w tym stylu.

Cytat
I druga rzecz... Transakcja jest traktowana przez bazę w kontekście aktualnego identyfikatora połączenia z bazą, prawda?

TAK!

Cytat
Ale którego? Każdy mój juzer łączy się z bazą z użyciem (z punktu widzenia bazy) tego samego loginu i hasła. W rezultacie zapytanie o CONNECTION_ID() daje za każdym razem inny rezultat.

Inne polaczenie z baza, to jest tylko resource polaczenia nic wiecej i transakcja dziala tylo na tym polaczeniu. Troche dziwne by bylo jak by 1 user mogl wycofywac operacje 2 userowi

Cytat
Czy mogę w ten sposób bezpiecznie używać transakcji, nie martwiąc się, ze jeden juzer wycofa transakcję drugiego?

Tak, jesli nie dowierzasz to poczytaj o transakcjach, radze tez poczytac o ACID. Kazda ksiazka do SQLa (no wiekszosc teori baz danych) zawiera tego typu materialy.
CzarnyKot
Cytat(ktuvok @ 2005-05-17 13:59:09)
...Czy transakcja odbywa się w ramach tego właśnie identyfikatora, czy w ramach CONNECTION_ID() zwracanego przez MySQL? TO zasadnicza różnica...

a po co wiele connect-ów?questionmark.gif

na początku pc_connect i do widzenia. (chyba)

w przypadku wykorzystania klasy do DB (np AdoDb) w ogole nie ma problemu poniewaz jesli wywolasz metode execute (tutaj odpowiedzialna za zapytania) to funkcja pierwsze sprawdzi czy nie dysponuje juz otwartym polaczeniem i jesli dysponuje to skorzysta wlasnie z tego konkretnego polaczenia
kustosz
no dobra ale co jak mam już otwarte połączenie adodb i w dalszej części pliku php inicjalizuję obiekt php korzystający z tej samej bazy który w konstruktorze otwiera nowe połączenie za pomocą adodb -> czy adodb sprawdza czy istnieje już połączenie czy po prostu otwiera następne z tymi samymi parametrami?

Kod
$conn = ADONewConnection(getDBDriverNameForADODB());
$conn->Connect($db_ip, $login, $pass, $db_name);

// to obiekt który otwiera nowe połączenie
$tabela = new tabela($sql, $columnes_definition);
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.