Das liegt nicht an PDO, sondern an der Transaktionsverwaltung von PostgreSQL. Siehe:
- Wie kann ich PostgreSQL anweisen, nicht die gesamte Transaktion abzubrechen, wenn eine einzelne Einschränkung fehlgeschlagen ist?
- Kann ich Postgresql bitten, Fehler innerhalb einer Transaktion zu ignorieren
- Rollback nach Fehler in der Transaktion
PostgreSQL setzt die Transaktion nicht zurück, sondern versetzt sie in einen abgebrochenen Zustand, in dem sie nur zurücksetzen kann und in dem alle Anweisungen außer ROLLBACK
Fehler melden:
(Ich bin überrascht, dass dies in der offiziellen Dokumentation nicht erwähnt wird; denke, ich muss einen Patch schreiben, um das zu verbessern.)
So. Wenn Sie versuchen, die Ausnahme in PDO abzufangen und zu schlucken, fangen Sie eine PHP-seitige Ausnahme ab, ändern aber nicht die Tatsache, dass sich die PostgreSQL-Transaktion in einem abgebrochenen Zustand befindet.
Wenn Sie Ausnahmen schlucken und die Transaktion weiter verwenden möchten, müssen Sie einen SAVEPOINT
erstellen
vor jeder Anweisung, die fehlschlagen könnte. Wenn dies fehlschlägt, müssen Sie ROLLBACK TO SAVEPOINT ...;
ausführen . Wenn es erfolgreich ist, können Sie RELEASE SAVEPOINT ...;
. Dies erlegt der Datenbank zusätzlichen Aufwand für die Transaktionsverwaltung auf, fügt Roundtrips hinzu und brennt Transaktions-IDs schneller durch (was bedeutet, dass PostgreSQL mehr Hintergrundbereinigungsarbeit leisten muss).
Im Allgemeinen ist es vorzuziehen, Ihr SQL stattdessen so zu entwerfen, dass es unter normalen Umständen nicht fehlschlägt. Beispielsweise können Sie die meisten Einschränkungen clientseitig validieren und die serverseitigen Einschränkungen als zweite Sicherheitsebene behandeln, während Sie die meisten Fehler clientseitig abfangen.
Wo dies unpraktisch ist, machen Sie Ihre Anwendung fehlertolerant, damit sie eine fehlgeschlagene Transaktion wiederholen kann. Manchmal ist dies ohnehin notwendig - zum Beispiel können Sie Sicherungspunkte im Allgemeinen nicht verwenden, um nach Deadlocks, Transaktionsabbrüchen oder Serialisierungsfehlern wiederherzustellen. Es kann auch nützlich sein, fehleranfällige Transaktionen so kurz wie möglich zu halten und nur die minimal erforderliche Arbeit zu erledigen, damit Sie weniger nachverfolgen und wiederholen müssen.
Also:Führen Sie nach Möglichkeit fehleranfälligen Datenbankcode in einer Wiederholungsschleife aus, anstatt eine Ausnahme zu schlucken. Stellen Sie sicher, dass Ihr Code die Informationen aufzeichnet, die er benötigt, um die gesamte Transaktion bei einem Fehler zu wiederholen, nicht nur die letzte Anweisung.
Denken Sie daran, alle Transaktion kann fehlschlagen:Der DBA könnte die Datenbank neu starten, um einen Patch anzuwenden, dem System könnte aufgrund eines außer Kontrolle geratenen Cron-Jobs der RAM ausgehen usw. Fehlertolerante Apps sind also sowieso ein gutes Design.
Requisiten an Sie, dass Sie zumindest PDO-Ausnahmen verwenden und Ausnahmen behandeln - Sie sind den meisten Entwicklern bereits weit voraus.