konto usunięte

Temat: posgtres transakcje

Mam taki oto kod:

foreach($import_data as $data) {
try {
$product = new Store_Product();
$product->merge($data);
$product->save();
$messages[] = 'Zaimportowano: '.$data['sku'].' / '.$data['name'];
}
catch (Exception $e) {
$errors[] = 'Błąd importu: '.$data['sku'].' / '.$data['name'].' / '.$e->getMessage();
}
}

W telegraficznym skrócie kod ten robi INSERTY do bazy Postgresa. Niestety gdy w jednym zapytaniu pojawi się błąd, np.:
Unique violation: 7 ERROR: duplicate key violates unique constraint "products_sku_key"
Kolejne zapytania nie zostaną wykonane:
SQLSTATE[25P02]: In failed sql transaction: 7 ERROR: current transaction is aborted, commands ignored until end of transaction block

Wygląda na to, że wszystkie zapytania wykonywane są w jakiejś transakcji (której nie uruchamiałem). Jak sobie poradzić z tym problemem?

konto usunięte

Temat: posgtres transakcje

Najlepiej najpierw sprawdź, czy nie ma podwójnego ID i nie próbuj wstawiać dwa razy...

Temat: posgtres transakcje

W MySQLu jest taka sprytna rzecz jak "insert ignore into". W przypadku zduplikowanego ID dany wiersz nie jest wstawiany, jednocześnie nie jest zgłaszany żaden błąd. Poszukaj, może w postgresie jest coś podobnego.
Piotr P.

Piotr P. Software Developer

Temat: posgtres transakcje

Łukasz Bandzarewicz:
Wygląda na to, że wszystkie zapytania wykonywane są w jakiejś transakcji (której nie uruchamiałem).

W pętli foreach złapany jest wyjątek który kończy działanie skryptu.

konto usunięte

Temat: posgtres transakcje

Piotr P.:

W pętli foreach złapany jest wyjątek który kończy działanie skryptu.

??
Jeśli wyjątek nie zostanie wyrzucony dalej, to skrypt nie zostanie zakończony. Skrypt zostanie zakończony tylko wtedy, jeśli wyjątek nie zostanie przechwycony.. no chyba, że jest jakaś magia php, o której nie wiem ;)
Piotr P.

Piotr P. Software Developer

Temat: posgtres transakcje

Łukasz Bandzarewicz:
Piotr P.:

W pętli foreach złapany jest wyjątek który kończy działanie skryptu.

??
Jeśli wyjątek nie zostanie wyrzucony dalej, to skrypt nie zostanie zakończony. Skrypt zostanie zakończony tylko wtedy, jeśli wyjątek nie zostanie przechwycony.. no chyba, że jest jakaś magia php, o której nie wiem ;)

Źle się wyraziłem :) Tak skrypt zostanie bezwarunkowo zakończony jeśli nie przechwycisz wyjątku, w innym (w tym) przypadku złapanie wyjątku zakończy pętle foreach tak samo jak break, więc następne kwerendy nie zostaną wysłane do bazy.

konto usunięte

Temat: posgtres transakcje

Łukasz Bandzarewicz:
Wygląda na to, że wszystkie zapytania wykonywane są w jakiejś transakcji (której nie uruchamiałem). Jak sobie poradzić z tym problemem?

W postgresql zwykle transakcje same się nie uruchamiają. Wyjściem wydaje się być wytropienie, gdzie zrobiło się "START TRANSACTION" i nie wywalenie tego (oraz "COMMIT" na koniec).

Ew. w bloku "catch" zrób "COMMIT; BEGIN TRANSACTION" - wtedy zakończysz porzpednią i rozpoczniesz nową.(na potrzeby tego comita co musi być na końcu).

konto usunięte

Temat: posgtres transakcje

Piotr P.:
Łukasz Bandzarewicz:
Piotr P.:

W pętli foreach złapany jest wyjątek który kończy działanie skryptu.

??
Jeśli wyjątek nie zostanie wyrzucony dalej, to skrypt nie zostanie zakończony. Skrypt zostanie zakończony tylko wtedy, jeśli wyjątek nie zostanie przechwycony.. no chyba, że jest jakaś magia php, o której nie wiem ;)

Źle się wyraziłem :) Tak skrypt zostanie bezwarunkowo zakończony jeśli nie przechwycisz wyjątku, w innym (w tym) przypadku złapanie wyjątku zakończy pętle foreach tak samo jak break, więc następne kwerendy nie zostaną wysłane do bazy.

Tu też się nie zgodzę..
W moim przypadku wyjątek jest łapany, obsługiwany i nie jest wyrzucany dalej, więc nic nie ma prawa przerwać pętli.
Poza tym tablica $errors jest wypełniania błędami do ostatniego rekordu w pętli.

Z problemem już sobie poradziłem, tak jak ktoś mi doradził - sprawdzam najpierw czy rekord o danym ID istnieje.
Poświęciłem chwilę na znalezienie przyczyny i dogrzebałem się do kilku ciekawych informacji - postgresa można skonfigurować tak, aby wszystkie zapytania w danym połączeniu uruchamiane były w transakcji (opcja autocommit), niestety nie doszedłem jeszcze do tego jak tę opcję wyłączyć i czy jest włączana domyślnie. Zapytanie SET AUTOCOMMIT = 'off' niestety rzuca mi wyjątek 'deprecated' - czyli moja wersja postgresa już tego nie obsługuje.

Czy ktoś już może posiadł wiedzę tajemną na temat AUTOCOMMIT w postgresie i byłby chętny się nią podzielić? ;)

Prawdopodobnie może to być też wina phpDoctrine, który też w jakiś magiczny sposób uruchamia transakcje.

Nieco z innej beczki:
Zauważyłem bardzo dziwną rzecz - jeśli jakieś zapytanie do postgresa spowoduje błąd, to w wyjątku php (PDO) wyświetlony zostanie fragment zapytania, które wykonywane jest zaraz po błędnym zapytaniu (że niby to ono powoduje błąd).. dziwne, prawda?

konto usunięte

Temat: posgtres transakcje

Adam T.:

Ew. w bloku "catch" zrób "COMMIT; BEGIN TRANSACTION" - wtedy zakończysz porzpednią i rozpoczniesz nową.(na potrzeby tego comita co musi być na końcu).

Tutaj sprawa niestety nie jest taka prosta, bo używam ORM-a (phpDoctrine) i nie piszę (a przynajmniej bardzo się staram) nie pisać nawet grama SQL-a ;)
Piotr P.

Piotr P. Software Developer

Temat: posgtres transakcje

Łukasz Bandzarewicz:
Źle się wyraziłem :) Tak skrypt zostanie bezwarunkowo zakończony jeśli nie przechwycisz wyjątku, w innym (w tym) przypadku złapanie wyjątku zakończy pętle foreach tak samo jak break, więc następne kwerendy nie zostaną wysłane do bazy.

Tu też się nie zgodzę..

Bardzo słusznie :)
Biję się w piersi i przepraszam za wprowadzone zamieszanie :)

Podobne tematy


Następna dyskusja:

Transakcje i PDO




Wyślij zaproszenie do