Това не е грешка на PDO, това е присъщо на управлението на транзакциите на PostgreSQL. Вижте:
- Как мога да кажа на PostgreSQL да не прекъсва цялата транзакция, когато едно ограничение е неуспешно?
- Мога ли да помоля на Postgresql да игнорира грешки в транзакция
- Връщане след грешка в транзакция
PostgreSQL не връща обратно транзакцията, но я настройва в прекъснато състояние, където може само да връща назад и където всички оператори с изключение на ROLLBACK
докладвайте за грешка:
(Изненадан съм, че не намирам това споменато в официалната документация; мисля, че ще трябва да напиша корекция, за да подобря това.)
Така. Когато опитате/хванете и погълнете изключението в PDO, вие улавяте изключение от страната на PHP, но не променяте факта, че транзакцията на PostgreSQL е в прекъснато състояние.
Ако искате да можете да преглъщате изключения и да продължите да използвате транзакцията, трябва да създайте SAVEPOINT
преди всяко изявление, което може да се провали. Ако не успее, трябва да ROLLBACK TO SAVEPOINT ...;
. Ако успее, можете да RELEASE SAVEPOINT ...;
. Това налага допълнително натоварване на базата данни за управление на транзакциите, добавя двупосочни пътувания и записва по-бързо идентификаторите на транзакции (което означава, че PostgreSQL трябва да извършва повече работа по почистване на заден план).
Като цяло е за предпочитане вместо това да проектирате своя SQL, така че да не се провали при нормални обстоятелства. Например, можете да валидирате повечето ограничения от страна на клиента, като третирате ограниченията от страна на сървъра като второ ниво на сигурност, докато прихващате повечето грешки от страна на клиента.
Когато това е непрактично, направете приложението си устойчиво на грешки, така че да може да опита отново неуспешна транзакция. Понякога това е необходимо така или иначе - например, обикновено не можете да използвате точки за запазване, за да възстановите от прекъсвания на транзакции в задънени блокировки или грешки при сериализация. Може също така да бъде полезно транзакциите, склонни към неуспехи, да бъдат възможно най-кратки, като се извършва само минималната необходима работа, така че да имате по-малко за проследяване и повтаряне.
Така че:Където е възможно, вместо да поглъщате изключение, изпълнете предразположен към повреда код на база данни в цикъл за повторен опит. Уверете се, че вашият код поддържа запис на информацията, от която се нуждае, за да опита отново цялата транзакция при грешка, а не само най-новото изявление.
Запомнете, всеки транзакцията може да е неуспешна:администраторът на бази данни може да рестартира базата данни, за да приложи корекция, системата може да изчерпи RAM поради неуспешно задание на cron и т.н. Така че устойчивите на откази приложения са добър дизайн така или иначе.
Поздравления за вас поне за използване на PDO изключения и обработка на изключения - вече сте много по-напред от повечето разработчици.