Transakcje w ramach transakcji

18

Jakie zachowanie wyświetliłby PostgreSQL, gdyby na przykład wywołano poniższy skrypt

BEGIN;
SELECT * FROM foo;
INSERT INTO foo(name) VALUES ('bar');
BEGIN; <- The point of interest
END;

Czy PostgreSQL odrzuci sekundę, BEGINczy też domyślnie zostanie podjęta decyzja o zatwierdzeniu, a następnie uruchomi BEGIN ENDblok na końcu jako osobna transakcja?

Alex
źródło

Odpowiedzi:

13

Potrzebna byłaby tak zwana „transakcja autonomiczna” (funkcja zapewniana przez Oracle). W tym momencie nie jest to jeszcze możliwe w PostgreSQL. Możesz jednak użyć SAVEPOINT :

BEGIN;
INSERT ...
SAVEPOINT a;
some error;
ROLLBACK TO SAVEPOINT a;
COMMIT;

Nie jest to całkowicie autonomiczna transakcja, ale umożliwia prawidłowe „każdą transakcję”. Możesz go użyć do osiągnięcia tego, czego oczekujesz od transakcji autonomicznych.

W przeciwnym razie nie ma w tym momencie innego rozsądnego rozwiązania.

Hans-Jürgen Schönig
źródło
13

Możesz spróbować samemu:

OSTRZEŻENIE: trwa już transakcja

Nie rozpoczyna żadnej nowej (pod) transakcji, ponieważ zagnieżdżone transakcje nie są zaimplementowane w PostgreSQL. (Możesz użyć magii w pl/pgsqlfunkcji, na przykład, która naśladuje to zachowanie).

Dzięki PostgreSQL 11 można by pomyśleć, że nowe rzeczywiste procedury składowane i ich zdolność do obsługi transakcji umożliwiłyby transakcje zagnieżdżone. Jednak zgodnie z dokumentacją tak nie jest:

W procedurach wywoływanych przez CALLpolecenie, a także w anonimowych blokach kodu ( DOpolecenie), możliwe jest zakończenie transakcji za pomocą poleceń COMMITi ROLLBACK. Nowa transakcja jest uruchamiana automatycznie po zakończeniu transakcji za pomocą tych poleceń, więc nie ma osobnego polecenia START TRANSAKCJA.

dezso
źródło
9

PostgreSQL nie obsługuje pod-transakcji, ale SAVEPOINTfunkcja może skutecznie odpowiedzieć na Twoje potrzeby. Cytując z dokumentacją Advanced Access warstwy do PG poprzez obietnic przez Witalija Tomilov na GitHub:

PostgreSQL nie ma odpowiedniej obsługi zagnieżdżonych transakcji, obsługuje tylko częściowe wycofywanie poprzez punkty zapisu w transakcjach. Różnica między tymi dwiema technikami jest ogromna, jak wyjaśniono dalej.

Właściwe wsparcie dla transakcji zagnieżdżonych oznacza, że ​​wynik udanej pod-transakcji nie jest wycofywany, gdy wycofywana jest jego transakcja nadrzędna. Jednak w przypadku punktów zapisu PostgreSQL wycofanie transakcji najwyższego poziomu powoduje również wycofanie wyniku wszystkich wewnętrznych punktów zapisu.

Punkty zapisu można wykorzystać do częściowego wycofania do wcześniejszego punktu w aktywnej transakcji. Na przykład, aby ustanowić punkt zapisu, a później cofnąć efekty wszystkich poleceń wykonanych po jego ustanowieniu:

BEGIN;
    INSERT INTO table1 VALUES (1);
    SAVEPOINT my_savepoint;
    INSERT INTO table1 VALUES (2);
    ROLLBACK TO SAVEPOINT my_savepoint;
    INSERT INTO table1 VALUES (3);
COMMIT;

Powyższa transakcja spowoduje wstawienie wartości 1 i 3, ale nie 2. Zobacz SAVEPOINTdokumentację, aby uzyskać więcej informacji.

Amir Ali Akbari
źródło
0

W przypadku Postgresql 9.5 lub nowszego można używać dynamicznych pracowników w tle udostępnianych przez rozszerzenie pg_background. Tworzy autonomiczną transakcję. Proszę odnieść się do strony github rozszerzenia. Sollution jest lepszy niż db_link. Kompletny przewodnik na temat obsługi transakcji autonomicznych w PostgreSQL

shcherbak
źródło