Czy transakcje w PostgreSQL za pośrednictwem `psycopg2` na kursor lub na połączenie?

10

Pracuję z PostgreSQL 9.3 przy użyciu psycopg2interfejsu API bazy danych.

Mam interfejs API DB ustawiony na minimalnym poziomie izolacji (tryb „automatycznego zatwierdzania”) i zarządzam własnymi transakcjami bezpośrednio przez SQL. Przykład:

cur = self.conn.cursor()
cur.execute("BEGIN;")
cur.execute("SELECT dbId, downloadPath, fileName, tags FROM {tableName} WHERE dlState=%s".format(tableName=self.tableName), (2, ))
ret = cur.fetchall()
cur.execute("COMMIT;")

Zasadniczo, czy transakcja, która jest uruchamiana przez cur.execute("BEGIN;")ograniczenie do tego samego kursora, czy też dotyczy całego połączenia ( self.conn.cursor())?

Niektóre bardziej złożone rzeczy, które robię, obejmują wiele oddzielnych operacji na bazie danych, które logicznie dzielę na funkcje. Ponieważ jest to wszystko w klasie, która ma połączenie jako członek, o wiele wygodniej jest tworzyć kursory w ramach każdej funkcji. Nie jestem jednak pewien, jak działa tworzenie kursorów w ramach transakcji.

Zasadniczo, jeśli transakcje dotyczą jednego połączenia, mogę po prostu utworzyć wiele kursorów w locie w ramach transakcji. Jeśli są na kursor, oznacza to, że muszę przesuwać kursor wszędzie. Który to jest?

Dokumentacja tego nie dotyczy, chociaż fakt, że możesz zadzwonić, connection.commit()daje mi całkowitą pewność, że kontrola transakcji dotyczy każdego połączenia.

Zmyślone imię
źródło

Odpowiedzi:

7

Transakcje są na sesję, tj. Na połączenie.

PostgreSQL nie obsługuje zawieszania i wznawiania transakcji, więc psycopg2 nie może ustawić ich dla kursora, chyba że pośrednio utworzy nowe połączenia za sceną.

W praktyce nie uważam kursorów psycopg2 za szczególnie użytecznych. Mogą zachować zestawy wyników, jeśli nie używasz przyrostowego pobierania z serwera, ale nie uważam ich za dobre dla wielu innych rzeczy.

Dlaczego ręcznie wydawania begini commitchociaż, zamiast przy użyciu metody połączenia dla nich?

Craig Ringer
źródło
AFICT z dokumentacji pokazuje, że cały model „DB API” wcale nie obsługuje jawnych transakcji.
Fałszywe imię
1
@FakeName Nie musisz tego jawnie begin. Jeśli żadna transakcja nie jest otwarta, rozpoczyna się nowa. Po prostu commitwytycz transakcje. Więc tak, model DB-API robi wsparcia jawnych transakcji.
Craig Ringer
1
Jeśli DB api robi to automatycznie, bez mojego specjalnego polecenia, to jest to w dużym stopniu domniemany początek. Poza tym nie ma to znaczenia, ponieważ (jak powiedziałem w pytaniu) korzystam z trybu automatycznego zatwierdzania, ponieważ nie chcę tych automatycznych BEGINinstrukcji. Nie chcę psycopg2tworzyć nowej transakcji dla każdej z nich SELECT.
Fałszywe imię
TL; DR w zasadzie chcę znać dokładny zakres wszystkich transakcji, ponieważ A. Jestem szalony, a B. bardzo pomaga w debugowaniu.
Fałszywe imię
1
Nie zdziwiłbym się, gdy pojawiały się w tym dziwne błędy. Autoryzacja AFAIK jest tak naprawdę przeznaczona do automatycznego zatwierdzania, a nie do ręcznego zarządzania transakcjami. Jeśli naprawdę chcesz ręcznie zarządzać zasięgiem transakcji, dodatkowy BEGINjest nieszkodliwy i zostanie po prostu zignorowany przez PostgreSQL WARNING: there is already a transaction in progress.
Craig Ringer
1

Z dokumentacji psycopg2 :

W Psycopg transakcje są obsługiwane przez klasę połączenia. Domyślnie przy pierwszym wysłaniu polecenia do bazy danych (za pomocą jednego z kursorów utworzonych przez połączenie) tworzona jest nowa transakcja. Następujące polecenia bazy danych zostaną wykonane w kontekście tej samej transakcji - nie tylko polecenia wydane przez pierwszy kursor, ale również polecenia wydane przez wszystkie kursory utworzone przez to samo połączenie. Jeśli jakiekolwiek polecenie zakończy się niepowodzeniem, transakcja zostanie przerwana i żadne dalsze polecenie nie zostanie wykonane do czasu wywołania metody rollback ().

Jednocześnie od wersji 2.4.2 istnieje autocommitatrybut (dodano wyróżnienie):

Atrybut odczytu / zapisu: jeśli Truesterownik nie obsługuje żadnej transakcji, a każda instrukcja wysłana do backendu ma natychmiastowy skutek; jeśli False nowa transakcja jest uruchamiana przy pierwszym wykonaniu polecenia : metody commit()lub rollback()należy ręcznie wywołać, aby zakończyć transakcję.

Tryb automatycznego zatwierdzania jest przydatny do wykonywania poleceń wymagających uruchomienia poza transakcją, takich jak CREATE DATABASElub VACUUM.

Wartość domyślna to False(ręczne zatwierdzanie) zgodnie ze specyfikacją DBAPI.

Stephen
źródło