Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> PDO - problem z unbuffered queries, w przypadku zapytań zwracających 1 rekord.
DeyV
post
Post #1





Grupa: Zarząd
Postów: 2 277
Pomógł: 6
Dołączył: 27.12.2002
Skąd: Wołów/Wrocław




Witam

Aż dziwnie się czuję - cały czas piszę na forum, ale strasznie dawno nie zadawałem pytań:)

Podczas pracy z PDO natrafiłem dziś na jednym z serwerów klienta, na nietypowy problem. Zaprezentuję go na przykładzie.

  1. <?php
  2. $Db = new PDO('mysql:host='.$GLOBALS['CONFIG']['db']['host'].'; dbname='.$GLOBALS['CONFIG']['db']['name'],
  3. $GLOBALS['CONFIG']['db']['user'], $GLOBALS['CONFIG']['db']['haslo'] );
  4. $Db -> setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
  5.  
  6.  
  7. $query = ' SELECT * FROM session LIMIT 1';
  8. $rWynik = $Db -> query( $query );
  9. $a1 = $rWynik->fetch();
  10.  
  11. var_dump( $a1 );
  12.  
  13. $query = ' SELECT 1 ';
  14. $rWynik2 = $Db -> query( $query );
  15. $a2 = $rWynik2->fetch();
  16.  
  17. var_dump( $a2 );
  18. ?>


Pierwsze zapytanie wykonuje się poprawnie, i zwracana jest (var_dump) tablica zawierająca 1 rekord. (zgodnie z oczekiwaniami (IMG:http://forum.php.pl/style_emoticons/default/smile.gif) )

Niestety - 2 zapytanie się nie wykonuje, wyrzucając wyjątek o treści:
Cytat
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY000]: General error: 2014
Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll().
Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute.' in /test/test.php:35
Stack trace:
#0 /test/test.php(35): PDO->query(' SELECT 1 ')
#1 {main}
thrown in /test/test.php on line 35


I wszystko wydawałoby się jasne, gdyby nie to, że błąd taki pojawia się tylko na jednym z serwerów na których pracuję.
Co więcej - jest to o tyle ciekawe, że błąd nie pojawia się za każdym razem, a po drugie - przecież wyraźnie widać, że 1 zapytanie może zwrócić tylko 1 rekord, a wiec fetch() powinno opróżnić bufer do końca.

Oczywiście - mógłbym rozwiązać ten problem tak jak radzi komunikat, ale po pierwsze - po to jest fetch by z niego korzystać, i nie zawsze wydaje się konieczne korzystanie z fetchAll, a ustawianie PDO::MYSQL_ATTR_USE_BUFFERED_QUERY też wygląda raczej na leczenie objawów niż przyczyn.

Czy spotkaliście się z taką sytuacją? I czy można poradzić coś adminowi w celu usunięcia tego problemu?


ps. proszę się nie śmiać z $GLOBALS - to na potrzeby testu (IMG:http://forum.php.pl/style_emoticons/default/winksmiley.jpg)
Go to the top of the page
+Quote Post
SongoQ
post
Post #2





Grupa: Przyjaciele php.pl
Postów: 2 923
Pomógł: 9
Dołączył: 25.10.2004
Skąd: Rzeszów - studia / Warszawa - praca

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


Za to globals mialem juz pisac ale na koncu zobaczylem (IMG:http://forum.php.pl/style_emoticons/default/tongue.gif) .

Ta odpowiedz moze Cie nie zadowoli ale ale stosuje sie petle while w celu wyczyszczenie bufora, lub np powtorne uzycie fetch()

  1. <?php
  2. while($a1 = $rWynik->fetch())
  3. print_r($a1);
  4. ?>


Naprawde fetch wykonuje sie 2x wiec ostatnie uzycie powoduje czysczenie bufora. Mozesz tam wywolac 2x fetch i spowoduje wyczysczenie. Dlaczego nieraz nie wysypuje sie, mozliwe ze cos innego ma wplyw na to, jakies inne zapytanie lub zupelnie cos innego. Jesli chodzi o fetchAll to z tego co wyczytalem to wyciaga wszystkie wyniki i laduje do pamieci wiec ten problem nie bedzie wystepowal.
Go to the top of the page
+Quote Post
DeyV
post
Post #3





Grupa: Zarząd
Postów: 2 277
Pomógł: 6
Dołączył: 27.12.2002
Skąd: Wołów/Wrocław




Cały kod zaprezentowałem tutaj. A jednak - problem, tak jak napisałem, pojawia się tylko raz na parę razy.
To naprawdę nie wygląda normalnie...

Tak - metodę z while znam. Można również skorzystać z jakieś specjalnej metody do zamykania kursora w pdo. Ale pytanie - czy zawsze trzeba tak robić?
Go to the top of the page
+Quote Post
SongoQ
post
Post #4





Grupa: Przyjaciele php.pl
Postów: 2 923
Pomógł: 9
Dołączył: 25.10.2004
Skąd: Rzeszów - studia / Warszawa - praca

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


Cytat
Ale pytanie - czy zawsze trzeba tak robić?

No wlasnie nic na ten temat nie znalazlem. Przegladalem manual po tym jak napisales tego posta i nic na ten temat nie znalazlem. Co do tego ze ten blad czasami wystepuje to troche dziwne, testowalem na 2 maszynach i u mnie zawsze ten blad wystepuje. Moze tak jak pisalem cos innego czysci buffor. Jak znajdziesz jakies informacje to napisz bardzo jestem ciekaw czemu tak jest.
Go to the top of the page
+Quote Post
DeyV
post
Post #5





Grupa: Zarząd
Postów: 2 277
Pomógł: 6
Dołączył: 27.12.2002
Skąd: Wołów/Wrocław




hmm Już ktoś wcześniej na to wpadł (IMG:http://forum.php.pl/style_emoticons/default/smile.gif)

http://bugs.php.net/bug.php?id=33833
> ... but this is not a bug.

Nie ma wyjścia - trzeba extendować PDO z własna metodą fetchRow() (IMG:http://forum.php.pl/style_emoticons/default/sad.gif)
A szkoda.
Go to the top of the page
+Quote Post
juzwa
post
Post #6





Grupa: Zarejestrowani
Postów: 144
Pomógł: 0
Dołączył: 10.07.2006

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


mam pytanie?

czy ewentualnie mógłbyś - jeśli byś znalazł - pokazać rozwiązanie - bo ja coś takiego mam (błąd 2014) gdy w funkcji jest procedura na pierwszym miejscu - jeśli jest jedna procedura to OK można przeżyć - ale gdy są dwie lub więcej albo gdy jest procedura -> cokolwiek sqelowego potem - to własnie mam problem z buforem

i nie wiem do tej pory jak to rozwiązać
Go to the top of the page
+Quote Post
SongoQ
post
Post #7





Grupa: Przyjaciele php.pl
Postów: 2 923
Pomógł: 9
Dołączył: 25.10.2004
Skąd: Rzeszów - studia / Warszawa - praca

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


@juzwa Zasada jest prosta ilosc zwroconych rekordow + 1 razy wywolanie fetch();
Go to the top of the page
+Quote Post
DeyV
post
Post #8





Grupa: Zarząd
Postów: 2 277
Pomógł: 6
Dołączył: 27.12.2002
Skąd: Wołów/Wrocław




Ja zdecyduję się chyba na takie rozwiązanie:
  1. <?php
  2. class PDOStatementE extends PDOStatement{
  3. public function fetchRow( $fetch_style, $cursor_orientation , $cursor_offset ){
  4. $aRow = $this->fetch( $fetch_style, $cursor_orientation , $cursor_offset );
  5. $this->closeCursor();
  6. return $aRow;
  7. }
  8. }
  9.  
  10. $Db = new PDO('mysql:host='.$GLOBALS['CONFIG']['db']['host'].'; dbname='.$GLOBALS['CONFIG']['db']['name'],
  11. $GLOBALS['CONFIG']['db']['user'], $GLOBALS['CONFIG']['db']['haslo']
  12. );
  13. $Db -> setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
  14. $Db -> setAttribute( PDO::ATTR_STATEMENT_CLASS, array( 'PDOStatementE', array( $this ) ) );
  15. ?>


Oczywiście oznacza to, że z fetchRow będę korzystał tylko wtedy, gdy wiem, że będzie zwrócony co najwyżej 1 rekord.
Go to the top of the page
+Quote Post
L00zak
post
Post #9





Grupa: Zarejestrowani
Postów: 58
Pomógł: 5
Dołączył: 2.05.2006

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


Błąd jest kozak, pojawia mi się tylko gdy w polu formularza wpisuję 'Wait a minute' jeśli mienię to już na 'Wait a minuta' to przechodzi bez problemu, zupełnie jak by interpretował to zdanie, że ma poczekać minute. Ostatnio z PDO jak z dzieckiem:D
Go to the top of the page
+Quote Post

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: 23.08.2025 - 02:19