To nie jest wina PDO, jest to nieodłączna cecha zarządzania transakcjami PostgreSQL. Zobacz:
- Jak mogę powiedzieć PostgreSQL, aby nie przerywał całej transakcji, gdy pojedyncze ograniczenie nie działa?
- Czy mogę poprosić Postgresql o ignorowanie błędów w transakcji
- Wycofanie po błędzie w transakcji
PostgreSQL nie wycofuje transakcji, ale ustawia ją w stan przerwania, w którym może tylko wycofać i gdzie wszystkie instrukcje z wyjątkiem ROLLBACK
zgłoś błąd:
(Jestem zaskoczony, że nie znalazłem tego w oficjalnej dokumentacji; myślę, że będę musiał napisać łatkę, aby to poprawić.)
Więc. Kiedy próbujesz/łapiesz i połkniesz wyjątek w PDO, przechwytujesz wyjątek po stronie PHP, ale nie zmieniasz faktu, że transakcja PostgreSQL jest w stanie przerwania.
Jeśli chcesz mieć możliwość przełknięcia wyjątków i dalszego korzystania z transakcji, musisz utwórz SAVEPOINT
przed każdą instrukcją, która może się nie powieść. Jeśli to się nie powiedzie, musisz ROLLBACK TO SAVEPOINT ...;
. Jeśli się powiedzie, możesz RELEASE SAVEPOINT ...;
. Nakłada to dodatkowe obciążenie na bazę danych w zakresie zarządzania transakcjami, dodaje rundy w obie strony i szybciej przepala identyfikatory transakcji (co oznacza, że PostgreSQL musi wykonać więcej prac związanych z czyszczeniem tła).
Ogólnie lepiej jest zaprojektować SQL tak, aby nie zawodził w normalnych okolicznościach. Na przykład możesz sprawdzić poprawność większości ograniczeń po stronie klienta, traktując ograniczenia po stronie serwera jako drugi poziom pewności, jednocześnie wyłapując większość błędów po stronie klienta.
Jeśli jest to niepraktyczne, spraw, aby aplikacja była odporna na błędy, aby mogła ponowić próbę nieudanej transakcji. Czasami i tak jest to konieczne — na przykład zazwyczaj nie można używać punktów zapisu do odzyskiwania po przerwaniach transakcji lub niepowodzeniach serializacji. Przydatne może być również utrzymywanie jak najkrótszych transakcji podatnych na awarie, wykonując tylko minimalną wymaganą pracę, dzięki czemu masz mniej do śledzenia i powtarzania.
Tak więc:Tam, gdzie to możliwe, zamiast połykania wyjątku, uruchom podatny na awarie kod bazy danych w pętli ponawiania. Upewnij się, że Twój kod rejestruje informacje potrzebne do ponowienia całej transakcji w przypadku błędu, a nie tylko najnowszego wyciągu.
Pamiętaj, dowolne transakcja może się nie powieść:DBA może zrestartować bazę danych, aby zastosować poprawkę, systemowi może zabraknąć pamięci RAM z powodu niekontrolowanego zadania crona itp. Tak więc aplikacje odporne na awarie i tak są dobrym projektem.
Prośba o przynajmniej używanie wyjątków PDO i obsługę wyjątków - już wyprzedzasz większość programistów.