2009-08-15 5 views
17

Tengo una aplicación python que abre una conexión de base de datos que puede colgar en línea durante horas, pero a veces el servidor de base de datos se reinicia y mientras python todavía tiene la conexión no funcionará con la excepción OperationalError.Asegurándome de que la conexión de base de datos psycopg2 viva

Así que estoy buscando cualquier método confiable para "hacer ping" a la base de datos y saber que la conexión está activa. Revisé una documentación de psycopg2 pero no puedo encontrar nada de eso. Claro que puedo emitir una instrucción SQL simple como SELECT 1 y atrapar la excepción, pero espero que haya un método nativo, algo así como PHP pg_connection_status

Gracias.

Respuesta

8

pg_connection_status se implementa utilizando PQstatus. psycopg no expone esa API, por lo que la verificación no está disponible. Los únicos dos lugares a los que psycopg llama PQstatus son cuando se establece una nueva conexión y al comienzo de la ejecución. Entonces, sí, deberá emitir una declaración SQL simple para averiguar si la conexión aún está allí.

+0

Llegué a la misma conclusión al leer las fuentes de psycopg2. Gracias. – HardQuestions

+0

Presentará la solicitud al autor psycopg para agregar dicha funcionalidad. – HardQuestions

+0

Vea la respuesta de Jaymon a continuación. – sage88

30

Esta pregunta es muy viejo, pero todavía aparece en las búsquedas de Google por lo que creo que es importante saber que la instancia psycopg2.connection ahora tiene un closed attribute que serán 0 cuando la conexión está abierta, y mayor que cero cuando la conexión es cerrado. El siguiente ejemplo debe demostrar:

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

Ha intentado matar las conexiones de la base de datos del controlador TCP (en Windows). 'connection.closed' desafortunadamente no cambiará el valor. – Vyktor

+0

@Vyktor ¡Tienes razón! El problema es que la conexión de Python no sabe que se ha cortado hasta que intenta comunicarse con el DB. He actualizado el ejemplo. La buena noticia es que puede ajustar el código de ejecución de la consulta para verificar la conexión en caso de error y volver a conectar según corresponda. – Jaymon

+0

Mi conexión se cerró durante una consulta porque la base de datos se reinició, 'cur.execute ('SELECT 1')' lanzó un 'InterfaceError' en mi caso con el mensaje' cursor already closed' – raphael

6

connection.closed no refleja una conexión cerrada/cortado por el servidor. Solo indica una conexión cerrada por el cliente usando connection.close()

Para asegurarse de que la conexión sigue siendo válida, lea la propiedad connection.isolation_level. Esto generará un OperationalError con pgcode == "57P01" en caso de que la conexión esté muerta.

Esto agrega un poco de latencia para un viaje de ida y vuelta a la base de datos, pero debería ser preferible a un SELECT 1 o similar.

import psycopg2 
dsn = "dbname=postgres" 
conn = psycopg2.connect(dsn) 

# ... some time elapses, e.g. connection within a connection pool 

try: 
    connection.isolation_level 
except OperationalError as oe: 
    conn = psycopg2.connect(dsn) 

c = conn.cursor() 
c.execute("SELECT 1") 
+1

Probado con psycopg2 2.5.2 y psql 8.4 - aislamiento el nivel siempre es cero sin importar qué. –

Cuestiones relacionadas