Discussion:
SQLSTATE[HY000]: General error: 2014
(zu alt für eine Antwort)
Thomas Mlynarczyk
2010-04-02 17:35:45 UTC
Permalink
Hallo,

Ich wollte per PDO ein paar Tabellen erzeugen und befüllen. Das
erfordert natürlich mehrere SQL-Statements, die ich zu drei PDO-Aufrufen
mit jeweils mehreren SQL-Statements zusammengefaßt hatte. Ich erhielt
die Fehlermeldung "SQLSTATE[HY000]: General error: 2014 Cannot execute
queries while other unbuffered queries are active. ...".

Tante Google förderte nun folgendes zutage:
<http://www.php.net/manual/de/ref.pdo-mysql.php#84588>

Dort wird zwar gesagt, wie dem Problem abzuhelfen ist, aber ich verstehe
nicht, was genau die Ursache ist. Ein CREATE-Statement gibt doch keine
Ergebnistabelle zurück, inwiefern sollte also besagte Query nach
Ausführung noch aktiv sein? Ist das ein Bug?

Gruß,
Thomas
--
Ce n'est pas parce qu'ils sont nombreux à avoir tort qu'ils ont raison!
(Coluche)
Thomas 'PointedEars' Lahn
2010-04-03 02:54:05 UTC
Permalink
Post by Thomas Mlynarczyk
Ich wollte per PDO ein paar Tabellen erzeugen und befüllen. Das
erfordert natürlich mehrere SQL-Statements, die ich zu drei PDO-Aufrufen
mit jeweils mehreren SQL-Statements zusammengefaßt hatte. Ich erhielt
die Fehlermeldung "SQLSTATE[HY000]: General error: 2014 Cannot execute
queries while other unbuffered queries are active. ...".
<http://www.php.net/manual/de/ref.pdo-mysql.php#84588>
Dort wird zwar gesagt, wie dem Problem abzuhelfen ist, aber ich verstehe
nicht, was genau die Ursache ist. Ein CREATE-Statement gibt doch keine
Ergebnistabelle zurück, inwiefern sollte also besagte Query nach
Ausführung noch aktiv sein? Ist das ein Bug?
Du musst noch richtig googlen lernen ;-)

<http://www.google.com/search?q=SQLSTATE[HY000]%3A+General+error%3A+2014>

führt zu per zweitem Haupttreffer zu

<http://bugs.php.net/bug.php?id=47504>

Kurz: It's not a bug, it's a feature.


HTH

PointedEars
Thomas Mlynarczyk
2010-04-03 17:58:12 UTC
Permalink
Post by Thomas 'PointedEars' Lahn
<http://bugs.php.net/bug.php?id=47504>
---
$pdo->query("INSERT [...]; -- I AM AN SQL COMMENT.");
Due to the ";" this is a multi-statement, executing two queries while
the second is only a comment. The second "result" can be accessed using
PDOStatement->nextRowset.
---

Also müßte ich jedesmal PDOStatement->nextRowset() so lange aufrufen,
bis "nichts mehr kommt"? Seltsam, daß es (lt. Bug-Report) unter Linux zu
funktionieren scheint [1]. Auch will mir nach wie vor nicht einleuchten,
wieso ein Kommentar ein neues Rowset erzeugen sollte. Davon abgesehen
hatte ich in meinem konkreten Fall keinen Kommentar:

$pdo->query( "CREATE TABLE ...; CREATE TABLE ..." );
$pdo->query( "CREATE TABLE ..." ); // Fehlermeldung

Es sollte doch eigentlich egal sein, ob ich die drei CREATE-Statements
nun in einen einzigen $pdo->query()-Aufruf pferche oder nicht -- wenn
der Aufruf etwas zurückliefert, daß ich abfragen könnte, ich das aber
nicht tue, dann sollte mit dem nächsten Aufruf dieses Etwas einfach
verworfen werden. So zumindest sehe ich das mal rein intuitiv.

Gruß,
Thomas


[1] Andererseits sollte ich mich ja mittlerweile daran gewöhnt haben,
daß Dinge, die unter anderen Betriebssystemen ganz klar ein Bug wären,
unter Windows als Feature gehandelt werden.
--
Ce n'est pas parce qu'ils sont nombreux à avoir tort qu'ils ont raison!
(Coluche)
Claus Reibenstein
2010-04-04 10:44:35 UTC
Permalink
Post by Thomas Mlynarczyk
Post by Thomas 'PointedEars' Lahn
<http://bugs.php.net/bug.php?id=47504>
---
$pdo->query("INSERT [...]; -- I AM AN SQL COMMENT.");
Due to the ";" this is a multi-statement, executing two queries while
the second is only a comment. The second "result" can be accessed using
PDOStatement->nextRowset.
---
Also müßte ich jedesmal PDOStatement->nextRowset() so lange aufrufen,
bis "nichts mehr kommt"?
Versuch's mal mit PDOStatement::closeCursor().
Post by Thomas Mlynarczyk
Auch will mir nach wie vor nicht einleuchten,
wieso ein Kommentar ein neues Rowset erzeugen sollte.
Steht doch oben: Weil der Kommentar als zweites Statement angesehen
wird. Hast Du selber hingeschrieben.
Post by Thomas Mlynarczyk
Davon abgesehen
$pdo->query( "CREATE TABLE ...; CREATE TABLE ..." );
Auch hier hast Du zwei Statements in einer Query. Laut Doku erwartet
PDO::query() aber immer nur _ein_ Statement.
Post by Thomas Mlynarczyk
$pdo->query( "CREATE TABLE ..." ); // Fehlermeldung
Es sollte doch eigentlich egal sein, ob ich die drei CREATE-Statements
nun in einen einzigen $pdo->query()-Aufruf pferche oder nicht
Nein, ist es nicht.

Lies Dir mal die Doku zu PDO::query() durch. Da steht das alles drin.

Gruß. Claus
Thomas Mlynarczyk
2010-04-04 12:42:57 UTC
Permalink
Post by Claus Reibenstein
Versuch's mal mit PDOStatement::closeCursor().
Hatte ich schon, hat aber nicht geholfen.
Post by Claus Reibenstein
Post by Thomas Mlynarczyk
Auch will mir nach wie vor nicht einleuchten,
wieso ein Kommentar ein neues Rowset erzeugen sollte.
Steht doch oben: Weil der Kommentar als zweites Statement angesehen
wird. Hast Du selber hingeschrieben.
Und seit wann haben Kommentare einen Rückgabewert?
<Statement>; -- <Kommentar>
sollte doch wohl genau so behandelt werden wie
<Statement>
Und selbst wenn ein Kommentar einen Rückgabewert haben sollte: Wenn ich
diesen nicht abfrage und stattdessen eine neue PDO::query mache, dann
sollte doch alles, was vom letzten Aufruf noch "übrig" ist, einfach
verworfen werden, oder?
Post by Claus Reibenstein
Post by Thomas Mlynarczyk
Davon abgesehen
$pdo->query( "CREATE TABLE ...; CREATE TABLE ..." );
Auch hier hast Du zwei Statements in einer Query. Laut Doku erwartet
PDO::query() aber immer nur _ein_ Statement.
Diese Query (für sich allein) funktionierte bei meinen Tests wunderbar.
Wenn PDO::query also tatsächlich nur _ein_ Statement erwartet, hätte ich
a) entweder eine Fehlermeldung erhalten müssen, oder b) wären nicht
beide Statements brav ausgeführt worden.
Post by Claus Reibenstein
Post by Thomas Mlynarczyk
$pdo->query( "CREATE TABLE ..." ); // Fehlermeldung
Erst hier trat der Fehler auf. Selbst wenn die vorangehende
Multi-Statement-Query als solche illegal gewesen sein sollte (und in
diesem Fall hätte ich, wie gesagt, bereits dort eine Fehlermeldung
erwartet), so sollte doch der nächste Aufruf definitiv nicht darunter
leiden müssen! Zumal es ja laut dem von meinem Namensvetter angeführten
Bug-Report unter Linux dieses Problem nicht zu geben scheint.
Post by Claus Reibenstein
Post by Thomas Mlynarczyk
Es sollte doch eigentlich egal sein, ob ich die drei CREATE-Statements
nun in einen einzigen $pdo->query()-Aufruf pferche oder nicht
Nein, ist es nicht.
In beiden Fällen bekommt der Server drei CREATE-Statements zum Ausführen
über dieselbe Verbindung in derselben Reihenfolge.
Post by Claus Reibenstein
Lies Dir mal die Doku zu PDO::query() durch. Da steht das alles drin.
Bezüglich des hier diskutierten Problems steht da nur
<zitat>
If you do not fetch all of the data in a result set before issuing your
next call to PDO::query(), your call may fail. Call
PDOStatement::closeCursor() to release the database resources associated
with the PDOStatement object before issuing your next call to PDO::query().
</zitat>

Erstens liefert mir CREATE doch keine Ergebnismenge zurück, weshalb es
also auch nichts zu "fetchen" geben sollte. Zweitens würde ich erwarten,
daß beim zweiten PDO::query()-Aufruf alle evtl. noch ausstehenden
"Überbleibsel" des ersten Aufrufs implizit entsorgt werden.

Was also sehe ich hier falsch?

Gruß,
Thomas
--
Ce n'est pas parce qu'ils sont nombreux à avoir tort qu'ils ont raison!
(Coluche)
Thomas 'PointedEars' Lahn
2010-04-04 13:36:39 UTC
Permalink
Post by Thomas Mlynarczyk
Post by Claus Reibenstein
Versuch's mal mit PDOStatement::closeCursor().
Hatte ich schon, hat aber nicht geholfen.
Post by Claus Reibenstein
Post by Thomas Mlynarczyk
Auch will mir nach wie vor nicht einleuchten,
wieso ein Kommentar ein neues Rowset erzeugen sollte.
Steht doch oben: Weil der Kommentar als zweites Statement angesehen
wird. Hast Du selber hingeschrieben.
Und seit wann haben Kommentare einen Rückgabewert?
Sieht tatsächlich nicht so aus:

mysql> -- foo
mysql>

Muss aber nichts heissen.
Post by Thomas Mlynarczyk
<Statement>; -- <Kommentar>
sollte doch wohl genau so behandelt werden wie
<Statement>
Nein, eben nicht.
Post by Thomas Mlynarczyk
Und selbst wenn ein Kommentar einen Rückgabewert haben sollte: Wenn ich
diesen nicht abfrage und stattdessen eine neue PDO::query mache, dann
sollte doch alles, was vom letzten Aufruf noch "übrig" ist, einfach
verworfen werden, oder?
Oder.
Post by Thomas Mlynarczyk
Post by Claus Reibenstein
Post by Thomas Mlynarczyk
$pdo->query( "CREATE TABLE ...; CREATE TABLE ..." );
Auch hier hast Du zwei Statements in einer Query. Laut Doku erwartet
PDO::query() aber immer nur _ein_ Statement.
Diese Query (für sich allein) funktionierte bei meinen Tests wunderbar.
Wenn PDO::query also tatsächlich nur _ein_ Statement erwartet,
Da gibt es kein Wenn:

,-<http://php.net/manual/en/pdo.query.php>
|
| PDO::query — Executes an SQL statement, returning a result set as a
| PDOStatement object
| [...]
| PDO::query() executes an SQL statement in a single function call,
| returning the result set (if any) returned by the statement as a
| PDOStatement object.
Post by Thomas Mlynarczyk
hätte ich
a) entweder eine Fehlermeldung erhalten müssen, oder b) wären nicht
beide Statements brav ausgeführt worden.
Nicht unbedingt. Was MySQL aus mehreren Statements in einer Query macht,
ist PDO::query() egal, da es eben nicht für mehrere Queries in einem Aufruf
ausgelegt ist.
Post by Thomas Mlynarczyk
Post by Claus Reibenstein
Post by Thomas Mlynarczyk
$pdo->query( "CREATE TABLE ..." ); // Fehlermeldung
Erst hier trat der Fehler auf. Selbst wenn die vorangehende
Multi-Statement-Query als solche illegal gewesen sein sollte (und in
diesem Fall hätte ich, wie gesagt, bereits dort eine Fehlermeldung
erwartet), so sollte doch der nächste Aufruf definitiv nicht darunter
leiden müssen!
Du gehst davon aus, dass alle Abfragen beendet sein müssen, bevor Du einen
weiteren Aufruf von PDO::query() machst, d.h. dass es sich hier in jedem
Fall um synchrone Verarbeitung handelt. Das muss aber nicht so sein, und
offensichtlich ist es hier nicht so.
Post by Thomas Mlynarczyk
Zumal es ja laut dem von meinem Namensvetter angeführten
Bug-Report unter Linux dieses Problem nicht zu geben scheint.
Es kann (muss aber nicht) mit dem MySQL-Client zu tun haben:

<http://www.php.net/manual/de/ref.pdo-mysql.php#84688>

(befindet sich nur ein Posting über Deiner Referenz)
Post by Thomas Mlynarczyk
Post by Claus Reibenstein
Post by Thomas Mlynarczyk
Es sollte doch eigentlich egal sein, ob ich die drei CREATE-Statements
nun in einen einzigen $pdo->query()-Aufruf pferche oder nicht
Nein, ist es nicht.
In beiden Fällen bekommt der Server drei CREATE-Statements zum Ausführen
über dieselbe Verbindung in derselben Reihenfolge.
Woher willst Du das wissen?
Post by Thomas Mlynarczyk
Post by Claus Reibenstein
Lies Dir mal die Doku zu PDO::query() durch. Da steht das alles drin.
Bezüglich des hier diskutierten Problems steht da nur
<zitat>
If you do not fetch all of the data in a result set before issuing your
next call to PDO::query(), your call may fail. Call
PDOStatement::closeCursor() to release the database resources associated
with the PDOStatement object before issuing your next call to
PDO::query(). </zitat>
Erstens liefert mir CREATE doch keine Ergebnismenge zurück, [...]
Doch, tut es:

mysql> CREATE DATABASE foo;
Query OK, 1 row affected (0.31 sec)

mysql> USE foo;
Database changed

mysql> CREATE TABLE bar (baz VARCHAR(255));
Query OK, 0 rows affected (0.01 sec)
Post by Thomas Mlynarczyk
[...]
Zweitens würde ich erwarten, daß beim zweiten PDO::query()-Aufruf alle
evtl. noch ausstehenden "Überbleibsel" des ersten Aufrufs implizit
entsorgt werden.
Offensichtlich ist das nicht so.


PointedEars
Thomas Mlynarczyk
2010-04-04 16:10:51 UTC
Permalink
Post by Thomas 'PointedEars' Lahn
Post by Thomas Mlynarczyk
<Statement>; -- <Kommentar>
sollte doch wohl genau so behandelt werden wie
<Statement>
Nein, eben nicht.
Es wird dann also eine Art No-Op-Statement ausgeführt?
Post by Thomas 'PointedEars' Lahn
<http://www.php.net/manual/de/ref.pdo-mysql.php#84688>
Bingo. Ich habe es gerade nochmal getestet: Der Fehler tritt bei PHP 5.2
auf, nicht jedoch bei PHP 5.3! Es ist also definitiv ein Bug, der mit
PHP 5.3 behoben wurde.

Gruß,
Thomas
--
Ce n'est pas parce qu'ils sont nombreux à avoir tort qu'ils ont raison!
(Coluche)
Thomas 'PointedEars' Lahn
2010-04-04 18:11:44 UTC
Permalink
Post by Thomas Mlynarczyk
Post by Thomas 'PointedEars' Lahn
Post by Thomas Mlynarczyk
<Statement>; -- <Kommentar>
sollte doch wohl genau so behandelt werden wie
<Statement>
Nein, eben nicht.
Es wird dann also eine Art No-Op-Statement ausgeführt?
Wenn Du so willst, ja.
Post by Thomas Mlynarczyk
Post by Thomas 'PointedEars' Lahn
<http://www.php.net/manual/de/ref.pdo-mysql.php#84688>
Bingo. Ich habe es gerade nochmal getestet: Der Fehler tritt bei PHP 5.2
auf, nicht jedoch bei PHP 5.3! Es ist also definitiv ein Bug, der mit
PHP 5.3 behoben wurde.
Definitiv ist da (ohne bestätigten Bugreport) gar nichts, und sich darauf
zu verlassen, dass etwas funktioniert, welches lt. Dokumentation nicht
funktioniert, ist bestenfalls inkompetent.

Mir stellt sich die Situation so dar:

,-----. ,-------------. ,-----------. ,---------.
| php | | $pdo : PDO | | mysql.so | | mysqld |
`--.--' `------.------' `-----.-----' `----.----'
: : : :
: query(...) : : :
:------------>: mysql_query(...) : :
: :------------------>: CREATE ... :
: : :--------------->:
: : :<---------------:
: : :
: : : CREATE ... :
: : :--------------->:
: query(...) : :<---------------:
:------------>X : :
: :<------------------: :
:<------------: : :
: : : :

An der Stelle X gibt es die Kollision und Du bekommst von der PDO-
Implementation die Fehlermeldung

| [...] Cannot execute queries while other unbuffered queries are active

(das Schlüsselwort hier ist *unbuffered*). Ist jetzt in diesem Ablauf eine
Komponente schneller als Dein PHP-Script, hast Du Glück und es gibt keine
Kollision. Das ist aber alles andere als verlässlich (race condition).


PointedEars
Thomas Mlynarczyk
2010-04-04 19:54:51 UTC
Permalink
Post by Thomas 'PointedEars' Lahn
,-----. ,-------------. ,-----------. ,---------.
| php | | $pdo : PDO | | mysql.so | | mysqld |
`--.--' `------.------' `-----.-----' `----.----'
An der Stelle X gibt es die Kollision und Du bekommst von der PDO-
Implementation die Fehlermeldung
Hm. Wenn ich Dein Diagramm richtig interpretiere, könnte eine Kollision
auch dann auftreten, wenn es nur *ein* CREATE gibt. Ein zwischen die
Queries gesetztes fetchAll() (oder was auch immer -- bei CREATE gibt es
ja nichts zu "fetchen") würde ggf. warten, bis der "Antwortpfeil" von
mysql.so eintrifft? Und PDO::query wartet eben nicht auf evtl. noch
ausstehende "Antwortpfeile"?

Den habe ich noch gefunden: <http://bugs.php.net/42499>. Und demnach ist
es wohl doch ein Bug, der mit PHP 5.3 gefixt wurde.

Gruß,
Thomas
--
Ce n'est pas parce qu'ils sont nombreux à avoir tort qu'ils ont raison!
(Coluche)
Thomas 'PointedEars' Lahn
2010-04-04 21:23:31 UTC
Permalink
Post by Thomas Mlynarczyk
Post by Thomas 'PointedEars' Lahn
,-----. ,-------------. ,-----------. ,---------.
| php | | $pdo : PDO | | mysql.so | | mysqld |
`--.--' `------.------' `-----.-----' `----.----'
An der Stelle X gibt es die Kollision und Du bekommst von der PDO-
Implementation die Fehlermeldung
Hm. Wenn ich Dein Diagramm richtig interpretiere, könnte eine Kollision
auch dann auftreten, wenn es nur *ein* CREATE gibt.
Ja, wenn z.B. die Tabelle das Ergebnis einer komplexen Abfrage ist, d.h.

CREATE TABLE ... SELECT ...;

so halte ich das für durchaus möglich.
Post by Thomas Mlynarczyk
Ein zwischen die Queries gesetztes fetchAll() (oder was auch immer --
bei CREATE gibt es ja nichts zu "fetchen")
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Diese Theorie von Dir habe ich bereits widerlegt.
Post by Thomas Mlynarczyk
würde ggf. warten, bis de "Antwortpfeil" von mysql.so eintrifft? Und
PDO::query wartet eben nicht auf evtl. noch ausstehende "Antwortpfeile"?
So hab' ich das zumindest verstanden:

,-<http://php.net/manual/en/class.pdo.php>
|
| The PDO class
| Introduction
|
| Represents a connection between PHP and a database server.

Über *eine* Datenbankverbindung kann AFAIK nur eine Anweisung bzw. eine
Reihe von Anweisungen in einer Meta-Anweisung gesendet werden (der DB-
Server übernimmt dann die Nacheinanderausführung der zusammenhängenden
Anweisungen oder parallelisiert die Ausführung falls möglich).

Mit einer gepufferten Abfrage ("buffered query") müsste (Vermutung) von der
PDO-Implementation entsprechend die neue Abfrage in eine Warteschlage
gestellt werden und erst dann an den DB-Server gesendet werden, wenn das
Ergebnis der vorherigen Abfrage vorliegt.
Post by Thomas Mlynarczyk
Den habe ich noch gefunden: <http://bugs.php.net/42499>. Und demnach ist
es wohl doch ein Bug, der mit PHP 5.3 gefixt wurde.
Das geht daraus _nicht_ hervor. (Englisch ist nicht Deine Stärke, oder?)
Da steht sinngemäss: Jemand hat das beschriebene Verhalten bemerkt, das von
6 von 6 Leuten reproduziert werden konnte, und einen seltsamen Patch dafür
vorgeschlagen. Jemand vom PHP-Team fühlte sich angep*sst, der Status des
Bugs ist zur Zeit "No Feedback" (nicht etwa Verified, oder gar Closed), und
das "Problem" existiert lt. "stormi at laposte dot net" in PHP 5.2.6 noch.
Alles andere ist Spekulation (Deinerseits).


PointedEars
Thomas 'PointedEars' Lahn
2010-04-04 22:01:41 UTC
Permalink
Post by Thomas 'PointedEars' Lahn
Post by Thomas Mlynarczyk
Den habe ich noch gefunden: <http://bugs.php.net/42499>. Und demnach ist
es wohl doch ein Bug, der mit PHP 5.3 gefixt wurde.
Das geht daraus _nicht_ hervor. (Englisch ist nicht Deine Stärke, oder?)
Da steht sinngemäss: Jemand hat das beschriebene Verhalten bemerkt, das
von 6 von 6 Leuten reproduziert werden konnte, und einen seltsamen Patch
dafür vorgeschlagen. Jemand vom PHP-Team fühlte sich angep*sst, der
Status des Bugs ist zur Zeit "No Feedback" (nicht etwa Verified, oder gar
Closed), und das "Problem" existiert lt. "stormi at laposte dot net" in
PHP 5.2.6 noch. Alles andere ist Spekulation (Deinerseits).
OK, sorry, anscheinend ist das tatsächlich in PHP 5.3 behoben worden. Das
Posting von "uw at php.net" hatte ich übersehen. (Soviel zu meinem Englisch
;-))

Danke für den Hinweis.


PointedEars
Thomas Mlynarczyk
2010-04-05 11:49:12 UTC
Permalink
Post by Thomas 'PointedEars' Lahn
Post by Thomas Mlynarczyk
Hm. Wenn ich Dein Diagramm richtig interpretiere, könnte eine Kollision
auch dann auftreten, wenn es nur *ein* CREATE gibt.
Ja, wenn z.B. die Tabelle das Ergebnis einer komplexen Abfrage ist, d.h.
CREATE TABLE ... SELECT ...;
so halte ich das für durchaus möglich.
Demnach wäre

$pdo->query( "CREATE TABLE foo ..." );
$pdo->query( "CREATE TABLE bar ..." );

diesbezüglich potentiell fehleranfällig.

Ich muß also darauf achten, nach einer Query stets eine wie auch immer
geartete Antwort abzufragen, bevor ich eine neue Query starte. Und im
allgemeinen Fall sollte closeCursor genau das tun? Ich sollte folglich
obigen Code wie folgt ergänzen, um auf der sicheren Seite zu sein:

$stmt = $pdo->query( "CREATE TABLE foo ..." );
$stmt->closeCursor();
$pdo->query( "CREATE TABLE bar ..." );
Post by Thomas 'PointedEars' Lahn
Über *eine* Datenbankverbindung kann AFAIK nur eine Anweisung bzw. eine
Reihe von Anweisungen in einer Meta-Anweisung gesendet werden (der DB-
Server übernimmt dann die Nacheinanderausführung der zusammenhängenden
Anweisungen oder parallelisiert die Ausführung falls möglich).
Heißt das, pro PDO-Instanz nur *ein* PDO::query-Aufruf?
Post by Thomas 'PointedEars' Lahn
Mit einer gepufferten Abfrage ("buffered query") müsste (Vermutung) von der
PDO-Implementation entsprechend die neue Abfrage in eine Warteschlage
gestellt werden und erst dann an den DB-Server gesendet werden, wenn das
Ergebnis der vorherigen Abfrage vorliegt.
Ich dachte immer, "buffered" bezieht sich auf das zurückgelieferte
Ergebnis, das komplett zwischengespeichert wird, nicht auf die noch
anstehenden Queries. Wobei das eine natürlich Auswirkungen auf das
andere haben könnte. Oder bedeutet "unbuffered" soviel wie "immer raus
mit den Queries, der Programmierer kümmert sich schon darum, daß es
keine Synchronisationsprobleme gibt", wohingegen bei "buffered"
automatisch dafür gesorgt wird, daß immer schön eins nach dem anderen
passiert -- evtl. auf Kosten der Performance?

Gruß,
Thomas
--
Ce n'est pas parce qu'ils sont nombreux à avoir tort qu'ils ont raison!
(Coluche)
Thomas 'PointedEars' Lahn
2010-04-24 01:32:26 UTC
Permalink
Post by Thomas Mlynarczyk
Post by Thomas 'PointedEars' Lahn
Post by Thomas Mlynarczyk
Hm. Wenn ich Dein Diagramm richtig interpretiere, könnte eine Kollision
auch dann auftreten, wenn es nur *ein* CREATE gibt.
Ja, wenn z.B. die Tabelle das Ergebnis einer komplexen Abfrage ist, d.h.
CREATE TABLE ... SELECT ...;
so halte ich das für durchaus möglich.
Demnach wäre
$pdo->query( "CREATE TABLE foo ..." );
$pdo->query( "CREATE TABLE bar ..." );
diesbezüglich potentiell fehleranfällig.
Ich muß also darauf achten, nach einer Query stets eine wie auch immer
geartete Antwort abzufragen, bevor ich eine neue Query starte. Und im
allgemeinen Fall sollte closeCursor genau das tun?
PDO::closeCursor() soll lt. Dokumentation die Datenbankverbindung beenden,
aber das Prepared Statement in einem Zustand belassen, in dem es erneut
ausgeführt werden kann.

<http://php.net/manual/en/pdostatement.closecursor.php>
Post by Thomas Mlynarczyk
Ich sollte folglich obigen Code wie folgt ergänzen, um auf der sicheren
$stmt = $pdo->query( "CREATE TABLE foo ..." );
$stmt->closeCursor();
$pdo->query( "CREATE TABLE bar ..." );
Schaden kann's anscheinend nicht.
Post by Thomas Mlynarczyk
Post by Thomas 'PointedEars' Lahn
Über *eine* Datenbankverbindung kann AFAIK nur eine Anweisung bzw. eine
Reihe von Anweisungen in einer Meta-Anweisung gesendet werden (der DB-
Server übernimmt dann die Nacheinanderausführung der zusammenhängenden
Anweisungen oder parallelisiert die Ausführung falls möglich).
Heißt das, pro PDO-Instanz nur *ein* PDO::query-Aufruf?
Nein.
Post by Thomas Mlynarczyk
Post by Thomas 'PointedEars' Lahn
Mit einer gepufferten Abfrage ("buffered query") müsste (Vermutung) von
der PDO-Implementation entsprechend die neue Abfrage in eine Warteschlage
gestellt werden und erst dann an den DB-Server gesendet werden, wenn das
Ergebnis der vorherigen Abfrage vorliegt.
Ich dachte immer, "buffered" bezieht sich auf das zurückgelieferte
Ergebnis, das komplett zwischengespeichert wird, nicht auf die noch
anstehenden Queries.
Das verstehst Du wohl richtig und ich falcsh.
Post by Thomas Mlynarczyk
Wobei das eine natürlich Auswirkungen auf das andere haben könnte.
Oder bedeutet "unbuffered" soviel wie "immer raus
mit den Queries, der Programmierer kümmert sich schon darum, daß es
keine Synchronisationsprobleme gibt", wohingegen bei "buffered"
automatisch dafür gesorgt wird, daß immer schön eins nach dem anderen
passiert -- evtl. auf Kosten der Performance?
<http://php.net/manual/de/function.mysql-unbuffered-query.php>


PointedEars
Thomas Mlynarczyk
2010-04-25 22:12:45 UTC
Permalink
Post by Thomas 'PointedEars' Lahn
PDO::closeCursor() soll lt. Dokumentation die Datenbankverbindung beenden,
aber das Prepared Statement in einem Zustand belassen, in dem es erneut
ausgeführt werden kann.
<http://php.net/manual/en/pdostatement.closecursor.php>
"frees up the connection to the server" liest sich für mich nicht wie
"Datenbankverbindung beenden" -- aber siehe weiter unten...
Post by Thomas 'PointedEars' Lahn
Post by Thomas Mlynarczyk
Post by Thomas 'PointedEars' Lahn
Über *eine* Datenbankverbindung kann AFAIK nur eine Anweisung bzw. eine
Reihe von Anweisungen in einer Meta-Anweisung gesendet werden (der DB-
Server übernimmt dann die Nacheinanderausführung der zusammenhängenden
Anweisungen oder parallelisiert die Ausführung falls möglich).
Heißt das, pro PDO-Instanz nur *ein* PDO::query-Aufruf?
Nein.
Dann verstand ich Dich hier offenbar miß. Unter "Datenbankverbindung"
verstehe ich das, was z.B. mit mysql_connect() bzw. new PDO() aufgebaut
wird, bis daß es z.B. mit mysql_close() bzw. im Destruktor von PDO
beendet wird. Also eigentlich die Verbindung zu einem Datenbankserver,
nicht die über eine solche erfolgenden einzelnen
mysql_query()/PDO::query()-Aufrufe.
Post by Thomas 'PointedEars' Lahn
<http://php.net/manual/de/function.mysql-unbuffered-query.php>
Das hatte ich also doch noch richtig in Erinnerung. :-)

Gruß,
Thomas
--
Ce n'est pas parce qu'ils sont nombreux à avoir tort qu'ils ont raison!
(Coluche)
Claus Reibenstein
2010-04-04 16:39:47 UTC
Permalink
Post by Thomas Mlynarczyk
Post by Claus Reibenstein
Versuch's mal mit PDOStatement::closeCursor().
Hatte ich schon, hat aber nicht geholfen.
Das ist allerdings merkwürdig.
Post by Thomas Mlynarczyk
Post by Claus Reibenstein
Post by Thomas Mlynarczyk
Auch will mir nach wie vor nicht einleuchten,
wieso ein Kommentar ein neues Rowset erzeugen sollte.
Steht doch oben: Weil der Kommentar als zweites Statement angesehen
wird. Hast Du selber hingeschrieben.
Und seit wann haben Kommentare einen Rückgabewert?
<Statement>; -- <Kommentar>
sollte doch wohl genau so behandelt werden wie
<Statement>
Was genau hast Du an 'Due to the ";" this is a multi-statement,
executing two queries' nicht verstanden?
Post by Thomas Mlynarczyk
Post by Claus Reibenstein
Post by Thomas Mlynarczyk
$pdo->query( "CREATE TABLE ...; CREATE TABLE ..." );
Auch hier hast Du zwei Statements in einer Query. Laut Doku erwartet
PDO::query() aber immer nur _ein_ Statement.
Diese Query (für sich allein) funktionierte bei meinen Tests wunderbar.
Schön. Und?
Post by Thomas Mlynarczyk
Wenn PDO::query also tatsächlich nur _ein_ Statement erwartet, hätte ich
a) entweder eine Fehlermeldung erhalten müssen, oder b) wären nicht
beide Statements brav ausgeführt worden.
Dass etwas _zufällig_ funktioniert, bedeutet noch lange nicht, dass es
auch korrekt ist.
Post by Thomas Mlynarczyk
Post by Claus Reibenstein
Post by Thomas Mlynarczyk
$pdo->query( "CREATE TABLE ..." ); // Fehlermeldung
Erst hier trat der Fehler auf.
Genau dieses Problem ist in der Doku zu PDO::query() beschrieben.
Post by Thomas Mlynarczyk
If you do not fetch all of the data in a result set before issuing your
next call to PDO::query(), your call may fail.
Du hast die Stelle sogar gefunden.
Post by Thomas Mlynarczyk
Erstens liefert mir CREATE doch keine Ergebnismenge zurück, weshalb es
also auch nichts zu "fetchen" geben sollte.
Natürlich liefert Dir PDO::query() auch bei CREATE ein Ergebnis zurück.
Wie sonst solltest Du innerhalb von PHP feststellen können, ob der
CREATE auch geklappt hat bzw. warum er nicht geklappt hat?
Post by Thomas Mlynarczyk
Zweitens würde ich erwarten,
daß beim zweiten PDO::query()-Aufruf alle evtl. noch ausstehenden
"Überbleibsel" des ersten Aufrufs implizit entsorgt werden.
Was Du erwartest, ist jedoch leider nicht das, was in der o.g. Doku
geschrieben steht - und nur die zählt.

Gruß. Claus
Thomas Mlynarczyk
2010-04-04 19:28:17 UTC
Permalink
Claus Reibenstein schrieb:

[<Statement>; -- <Kommentar>]
Post by Claus Reibenstein
Was genau hast Du an 'Due to the ";" this is a multi-statement,
executing two queries' nicht verstanden?
<Statement>;;;;; wären demnach fünf (oder gar sechs) Queries?
Post by Claus Reibenstein
Post by Thomas Mlynarczyk
If you do not fetch all of the data in a result set before issuing your
next call to PDO::query(), your call may fail.
Demnach müßte ich also alle Daten des Result-Sets abholen, und dann
sollte es funktionieren. Nur -- *wie*?

$stmt = $pdo->query( "CREATE TABLE foo ...; CREATE TABLE bar ..." );
// In dieser Zeile alle Daten abholen -- wie? Dann weiter:
$pdo->query( "CREATE TABLE baz ..." );

Gruß,
Thomas
--
Ce n'est pas parce qu'ils sont nombreux à avoir tort qu'ils ont raison!
(Coluche)
Thomas 'PointedEars' Lahn
2010-04-04 19:52:53 UTC
Permalink
Post by Thomas Mlynarczyk
[<Statement>; -- <Kommentar>]
Post by Claus Reibenstein
Was genau hast Du an 'Due to the ";" this is a multi-statement,
executing two queries' nicht verstanden?
<Statement>;;;;; wären demnach fünf (oder gar sechs) Queries?
Nein, ein Syntaxfehler:

mysql> USE mysql;;;;;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
ERROR:
No query specified

ERROR:
No query specified

ERROR:
No query specified

ERROR:
No query specified

(Was ist eigentlich so schwierig daran, die Sache selbst auszuprobieren,
*bevor* man in der Newsgroup fragt?)
Post by Thomas Mlynarczyk
Post by Claus Reibenstein
Post by Thomas Mlynarczyk
If you do not fetch all of the data in a result set before issuing your
next call to PDO::query(), your call may fail.
Demnach müßte ich also alle Daten des Result-Sets abholen, und dann
sollte es funktionieren. Nur -- *wie*?
$stmt = $pdo->query( "CREATE TABLE foo ...; CREATE TABLE bar ..." );
$pdo->query( "CREATE TABLE baz ..." );
Mal abgesehen davon, dass Du das aus bekannten Gründen nicht tun willst:
PDOStatement::closeCursor() sollte genau das ermöglichen. Aber dann musst
Du mit Prepared Statements arbyten (was der Grund dafür sein dürfte, dass
es bei Dir bisher nicht funktioniert hat -- Du versuchtest, die Methode als
Klassenmethode aufzurufen):

<http://php.net/manual/en/pdostatement.closecursor.php>


PointedEars
Thomas Mlynarczyk
2010-04-04 20:01:00 UTC
Permalink
Post by Thomas 'PointedEars' Lahn
Post by Thomas Mlynarczyk
$stmt = $pdo->query( "CREATE TABLE foo ...; CREATE TABLE bar ..." );
$pdo->query( "CREATE TABLE baz ..." );
PDOStatement::closeCursor() sollte genau das ermöglichen. Aber dann musst
Du mit Prepared Statements arbyten (was der Grund dafür sein dürfte, dass
es bei Dir bisher nicht funktioniert hat -- Du versuchtest, die Methode als
Ich habe mit Prepared Statements und closeCursor() getestet --
funktioniert nicht.

Gruß,
Thomas
--
Ce n'est pas parce qu'ils sont nombreux à avoir tort qu'ils ont raison!
(Coluche)
Claus Reibenstein
2010-04-04 20:34:32 UTC
Permalink
Post by Thomas Mlynarczyk
Post by Claus Reibenstein
Was genau hast Du an 'Due to the ";" this is a multi-statement,
executing two queries' nicht verstanden?
<Statement>;;;;; wären demnach fünf (oder gar sechs) Queries?
Willst Du jetzt Hilfe, oder suchst Du nur Streit? Allmählich bekomme ich
an Ersterem so meine Zweifel.
Post by Thomas Mlynarczyk
Post by Claus Reibenstein
Post by Thomas Mlynarczyk
If you do not fetch all of the data in a result set before issuing your
next call to PDO::query(), your call may fail.
Demnach müßte ich also alle Daten des Result-Sets abholen, und dann
sollte es funktionieren. Nur -- *wie*?
Was ist denn so schwer daran, sich mal mit PDO im Allgemeinen und
PDOStatement im Speziellen zu beschäftigen? Ist die Doku wirklich so
unverständlich, dass Du das nicht selber hinbekommst? Was genau hast Du
daran nicht verstanden

Gruß. Claus
Thomas Mlynarczyk
2010-04-05 11:01:16 UTC
Permalink
Post by Claus Reibenstein
Willst Du jetzt Hilfe, oder suchst Du nur Streit?
Wenn Du solche Töne anschlägst, ist es wohl besser, diese Diskussion zu
beenden.
Post by Claus Reibenstein
Post by Thomas Mlynarczyk
Post by Thomas Mlynarczyk
If you do not fetch all of the data in a result set before issuing your
next call to PDO::query(), your call may fail.
Demnach müßte ich also alle Daten des Result-Sets abholen, und dann
sollte es funktionieren. Nur -- *wie*?
Was ist denn so schwer daran, sich mal mit PDO im Allgemeinen und
PDOStatement im Speziellen zu beschäftigen? Ist die Doku wirklich so
unverständlich, dass Du das nicht selber hinbekommst? Was genau hast Du
daran nicht verstanden
Ich habe auf verschiedene Art versucht, die laut der Fehlermeldung
offenbar noch nicht abgeholten Ergebnisdaten zwischen den beiden
Aufrufen zu holen. Weder closeCursor, fetchAll, rowCount noch nextRowset
führten zum Erfolg. Was habe ich übersehen?

Aufgrund des an anderer Stelle in diesem Thread von mir angeführten
Bug-Reports bin ich nun zu dem Schluß gelangt, daß es sich tatsächlich
um einen Bug handelt, der mit PHP 5.3 behoben wurde.

Gruß,
Thomas
--
Ce n'est pas parce qu'ils sont nombreux à avoir tort qu'ils ont raison!
(Coluche)
Claus Reibenstein
2010-04-05 21:38:32 UTC
Permalink
Post by Thomas Mlynarczyk
Post by Claus Reibenstein
Willst Du jetzt Hilfe, oder suchst Du nur Streit?
Wenn Du solche Töne anschlägst, ist es wohl besser, diese Diskussion zu
beenden.
Vermutlich hast Du Recht.

EOD

Gruß. Claus
Lesen Sie weiter auf narkive:
Loading...