2009-08-15 18 views
17

Mam aplikację python, która otwiera połączenie z bazą danych, która może zawiesić się online na kilka godzin, ale czasami serwer bazy danych restartuje się, a podczas gdy python nadal ma połączenie, nie zadziała z wyjątkiem OperationalError.Upewnianie się, że połączenie z bazą danych psycopg2 przy życiu

Poszukuję więc jakiejkolwiek niezawodnej metody "pingowania" bazy danych i wiem, że połączenie jest żywe. Sprawdziłem dokumentację psycopg2, ale nie mogę znaleźć czegoś takiego. Pewnie mogę wydać prostą instrukcję SQL, taką jak SELECT 1 i wychwycić wyjątek, ale mam nadzieję, że istnieje natywna metoda, coś w stylu PHP: PHP pg_connection_status

Dzięki.

Odpowiedz

8

pg_connection_status jest zaimplementowany przy użyciu PQstatus. psycopg nie ujawnia tego API, więc czek nie jest dostępny. Jedyne dwa miejsca, do których psycopg wywołuje sam PQstatus, to kiedy nawiązane zostaje nowe połączenie i na początku wykonywania. Tak, tak, musisz wydać prostą instrukcję SQL, aby sprawdzić, czy połączenie wciąż istnieje.

+0

Doszedłem do tego samego wniosku, czytając źródła psycopg2. Dzięki. – HardQuestions

+0

Złoży wniosek do autora psycopg, aby dodać taką funkcję. – HardQuestions

+0

Zobacz odpowiedź Jaymona poniżej. – sage88

30

To pytanie jest bardzo stary, ale nadal pojawia się w wynikach wyszukiwania Google, więc myślę, że to cenne wiedzieć, że instancja psycopg2.connection ma teraz closed attribute który będzie 0 gdy połączenie jest otwarte, a większy niż zero, gdy połączenie jest Zamknięte. Poniższy przykład powinien wykazać:

import psycopg2 
import subprocess 

connection = psycopg2.connect(
    database=database, 
    user=username, 
    password=password, 
    host=host, 
    port=port 
) 

print connection.closed # 0 

# restart the db externally 
subprocess.check_call("sudo /etc/init.d/postgresql restart", shell=True) 

# this query will fail because the db is no longer connected 
try: 
    cur = connection.cursor() 
    cur.execute('SELECT 1') 
except psycopg2.OperationalError: 
    pass 

print connection.closed # 2 
+3

Czy próbowałeś zabić połączenia z bazą danych uchwyt TCP (w systemie Windows). 'connection.closed' niestety nie zmieni wartości. – Vyktor

+0

@Vyktor Masz rację! Problem polega na tym, że połączenie Pythona nie wie, że zostało przerwane, dopóki nie spróbuje się komunikować z bazą danych. Zaktualizowałem przykład. Dobrą wiadomością jest to, że możesz zawinąć kod wykonujący kwerendę, aby sprawdzić połączenie pod kątem błędu i ponownie nawiązać połączenie. – Jaymon

+0

Moje połączenie zostało zamknięte podczas zapytania, ponieważ baza danych uruchomiona ponownie, 'cur.execute ('SELECT 1')' rzuciło 'InterfaceError' w moim przypadku z komunikatem' kursor już zamknięty' – raphael

6

connection.closed nie odzwierciedla połączenie zamknięte/zerwane przez serwer. Wskazuje tylko połączenie zamknięte przez klienta przy użyciu connection.close()

Aby upewnić się, że połączenie jest nadal ważne, przeczytaj właściwość connection.isolation_level. Spowoduje to wywołanie OperationalError z pgcode == "57P01" na wypadek, gdyby połączenie było martwe.

Dodaje to trochę opóźnienia do objazdu do bazy danych, ale powinno być lepsze niż SELECT 1 lub podobne.

+1

Testowane z psycopg2 2.5.2 i psql 8.4 - izolacja Poziom jest zawsze zerowy bez względu na wszystko. –

Powiązane problemy