PHP-Support Versionen: > 7.3 & 8.x

Themen rund um den praktischen Einsatz von Firebird. Fragen zu SQL, Performance, Datenbankstrukturen, etc.

Moderator: thorben.braun

Benutzeravatar
martin.koeditz
Beiträge: 377
Registriert: Sa 31. Mär 2018, 14:35

Moin Hamburgo,

ich möchte deinen Quellcode gar nicht durchforsten. Vielmehr benötige ich ein exemplarisches Beispiel, womit ich das Problem verifizieren kann. Sonst ist eine Fehlerbehebung äußerst schwierig.

Gruß
Martin
Martin Köditz
it & synergy GmbH
vr2
Beiträge: 158
Registriert: Fr 13. Apr 2018, 00:13

Hallo Hamburgo,
Hamburgo hat geschrieben: Mi 16. Nov 2022, 10:46 Verzichte ich auf den fbird_commit($link_or_trans_identifier[[Resource id #53]]) läuft alles problemlos, woraus ich schließe, das der fbird_commit auf die #53 auch Folgen für die Resource id #58 hat.

Was mache ich da falsch ?
Du bist in der Schleife ja bereits in einer Transaktion und wenn Du die committest, ist die natürlich abgeschlossen und der Cursor bzw insgesamt Dein Query-Objekt aus Firebirdsicht (das ja immer nur im Kontext einer TX existiert) ist Geschichte.

Um eine Aktion separat innerhalb einer TX zu committen, die aber bestehen zu lassen, gibt es mehrere Möglichkeiten, hier in dem Fall brauchst Du dafür eine weitere unabhängige TX. Schau mal unter Stichwort autonomous transaction bei Firebird oder Du machst es zu Fuß in php, indem Du eine weitere TX startest, und deren $link_or_trans_identifier Du beim commit in der Schleife verwendest. Befass Dich evtl auch noch mal mit Transaktionen und deren Zusammenspiel (isolation, wait/nowait, long running transactions), diesen Hintergrund brauchst Du hier.

Viele Grüße, Volker
Hamburgo
Beiträge: 120
Registriert: Di 28. Mai 2019, 17:28

Hallo Volker,

wie ich schon in einem vorherigen Post geschrieben habe, habe ich
den fbird_commit inzwischen nach der von Dir vorgeschlagenen
2. Syntax, was insoweit erfolgreich war, dass dieser keinen Error
mehr produziert.

fbird_commit($link_or_trans_identifier);

Wenn ich den SELECT absetze erhält dieser z.B. die "Resource id #53" und ich
erhalte als "result identifier" die "Resource id #58" zurück.

So ist es auch unter https://www.php.net/manual/en/function.ibase-query.php beschrieben.

Mit dem Result-Identifier "Resource id #58" starte ich nun meine While-Schleife mit dem
fbird_fetch_assoc("Resource id #58").

Der 1. Datensatz wird dann auch noch von der While-Schleife korrekt ausgeliefert.
Innerhalb der While-Schleife setze ich ein vorher als Selections-Kriterium gesetztes
Feld wieder per Update auf 0;

Das mache ich häufig und das funktioniert in Regel auch sehr gut und problemlos,
solange ich jedenfalls nach einem Update oder Insert keinen fbird_commit($link_or_trans_identifier);
absetze.

Setze ich jedoch nach dem Update einen fbird_commit("Resource id #53"); dann kommt
halt die Fehler-Meldung, was wohl bedeutet, dass mit dem Result-Identifier "Resource id #58"
auch etwas passiert und nicht nur mit der #53.

Jetzt könnte man als Erklärung vermuten, dass die "Resource id #58" so als eine Art "verwandte"
Child-ResourceID von der #53 mit-commited wird.

Dagegen spricht allerdings die Tatsache, dass ich in dieser While-Schleife noch so Einiges mehr
mache, z.B. noch 1 - 3 Select's auf andere Tabellen absetze und jeder dieser Selects immer
wieder dieSELBE "Resource id #53" erhält, also die theoretisch denkbare "Verwandschaft" zur
"Resource id #58" von FB selbst schon lange mehrfach wieder gekappt wurde.

Das ist für mich schon alles recht merkwürdig und nicht logisch bzw. kausal.
vr2
Beiträge: 158
Registriert: Fr 13. Apr 2018, 00:13

Hallo Hamburgo,
Hamburgo hat geschrieben: Sa 19. Nov 2022, 18:07 fbird_commit($link_or_trans_identifier);

Wenn ich den SELECT absetze erhält dieser z.B. die "Resource id #53" und ich
erhalte als "result identifier" die "Resource id #58" zurück.

So ist es auch unter https://www.php.net/manual/en/function.ibase-query.php beschrieben.
Ja, aber dort ist der Parameter ein db-handle (link) und kein transaction-handle (trans_identifier). Im fbird_commit($link_or_trans_identifier) kannst Du beide Arten von Ressourcen nutzen, deswegen haben die den Parameter auch so benannt.

Wenn Du das db-handle benutzt, operierst Du auf der default Transaktion der connection. Wenn Du ein transaction handle nutzt, auf einer separaten TX, und das brauchst Du hier. Schau mal unter https://www.php.net/manual/en/function.ibase-trans.php, dann wird das klarer. Du musst die commits innerhalb der Schleife mit/in einer separaten Transaktion machen, sonst committest Du die default TX, in der die Schleife läuft.

Grüße, Volker
Hamburgo
Beiträge: 120
Registriert: Di 28. Mai 2019, 17:28

Hallo Volker,

ok, da werde ich mich mal rein-arbeiten. Kann mir gut vorstellen,
das damit mein Problem in den Griff zu bekommen ist.

Aber trotzdem habe ich noch nicht so richtig verstanden, warum
bei einem Commit auf die "Resource id #53" dann auch die
"Resource id #58" betroffen ist.

Dann macht die explizite Angabe der Resource-ID im Commit
für mich nicht mehr viel Sinn, wenn eh alle mit der Verbindung
stehenden IDs tangiert werden.

Oder die Vergabe der verwandten IDs sollte erkennbar sein,
z.B. dass in meinem Fall die Ergebnis-ID "Resource id #58"
stattdessen "Resource id #53.1" lautet.

Dann wäre leichter erkennbar, dass die IDs etwas miteinander
zu tun haben und deshalb zusammen von einem Befehl betroffen
sein können.

Danke und Gruss
bfuerchau
Beiträge: 388
Registriert: Mo 7. Mai 2018, 18:09

Was immer der Treiber da macht, für die Firebird selber gilt dies so nicht.

In der DB gibt es Für Statements eine Statement-ID in der MON$STATEMENTS.
Diese kann i.W. dazu verwendet werden, per 2. Verbindung einen lang laufenden Query per Delete abzubrechen.
Aber nur Transaktionen können können per Commit/Rollback bestätigt oder zurückgedreht werden.
Diese werden in der MON$TRANSACTIONS festgehalten.
Je Connection ist nur 1 aktive Transaction erlaubt.

Nun gibts noch die Savepoints, mit denen man einen Zustand merken kann.
Allerdings kann man nur einen "Rollback to Savepoint" machen, einen "Commit to Savepoint" wiederum gibt es nicht.
Somit kann man auch eine Transaktion nur insgesamt committen oder zurücksetzen was dann alle Savepoints einschließt.

Die Firebird untersützt zusätzlich noch in PSQL die "autonomous transaction".
Diese kann mit Begin/End umschlossen werden und ist auch in "execute block" erlaubt.
Damit kann man z.B. Protokolleinträge vornehmen, die durch Rollback des Clients nicht zurückgedreht werden können.
Der Commit wird durch End automatisch durchgeführt, einen Rollback kann man nur mit "exception" erreichen, was durch ein umschließendes Exceptionhandling überwacht werden kann, ansonsten schlägt dies bis zum Client durch.
Antworten