2010-03-03 8 views
9

Estoy creando una API RESTful que necesita acceder a la base de datos. Estoy usando Restish, Oracle y SQLAlchemy. Sin embargo, trataré de enmarcar mi pregunta de la manera más genérica posible, sin tener en cuenta Restish u otras API web.Establecer tiempo de espera de conexión de base de datos en Python

Me gustaría poder establecer un tiempo de espera para una conexión que ejecuta una consulta. Esto es para garantizar que las consultas de larga ejecución se abandonen y la conexión se descarte (o recicle). Este tiempo de espera de consulta puede ser un valor global, es decir, no es necesario que lo cambie por consulta o creación de conexión.

Dado el siguiente código:

import cx_Oracle 
import sqlalchemy.pool as pool 

conn_pool = pool.manage(cx_Oracle) 
conn = conn_pool.connect("username/[email protected]") 
conn.ping() 

try: 
    cursor = conn.cursor() 
    cursor.execute("SELECT * FROM really_slow_query") 
    print cursor.fetchone() 
finally: 
    cursor.close() 

¿Cómo puedo modificar el código anterior para establecer un tiempo de espera de consulta sobre ella? ¿Este tiempo de espera también se aplicará a la creación de conexión?

Esto es similar a lo que hace el método setQueryTimeout (int seconds) de java.sql.Statement en Java.

Gracias

+0

Hola, veo que no se aceptan respuestas negativas ¿encontraste alguna otra solución para esto? – Ib33X

+0

No, no he podido hacer que esto funcione. Las soluciones sugeridas hasta ahora simplemente no funcionan. – oneself

+0

¿Por qué no funciona 'conn.cancel()'? ¿Qué pasa cuando pruebas la solución de Dmitry? – alldayremix

Respuesta

0

Usted podría mirar a la creación de PROFILE s en Oracle para poner fin a las consultas después de un cierto número de logical_reads_per_call y/o cpu_per_call

-3

del tiempo límite con el sistema de alarma

Aquí es cómo usar el timout del sistema operativo para hacer esto. Es genérico y funciona para otras cosas además de Oracle.

import signal 
class TimeoutExc(Exception): 
    """this exception is raised when there's a timeout""" 
    def __init__(self): Exception.__init__(self) 
def alarmhandler(signame,frame): 
    "sigalarm handler. raises a Timeout exception""" 
    raise TimeoutExc() 

nsecs=5 
signal.signal(signal.SIGALRM, alarmhandler) # set the signal handler function 
signal.alarm(nsecs)       # in 5s, the process receives a SIGALRM 
try: 
    cx_Oracle.connect(blah blah)    # do your thing, connect, query, etc 
    signal.alarm(0)       # if successful, turn of alarm 
except TimeoutExc: 
    print "timed out!"      # timed out!! 
+0

Esto no parece funcionar. Oracle no se interrumpe. – oneself

+0

Por supuesto, Oracle (en el servidor) no se interrumpe: usted dijo que quería "abandonar la consulta de larga ejecución", lo que significa que simplemente se da por vencido al esperar la respuesta. Si realmente quiere que Oracle deje de ejecutar la consulta, eso es completamente distinto, y no tan fácil, tendría que "matar la sesión" en el servidor ... –

+1

Lo que quise decir es que la consulta continúa ejecutándose ininterrumpidamente en el cliente. – oneself

11

para la consulta, puede consultar el temporizador y la llamada conn.cancel().

algo en esas líneas:

t = threading.Timer(timeout,conn.cancel) 
t.start() 
cursor = conn.cursor() 
cursor.execute(query) 
res = cursor.fetchall() 
t.cancel() 
+0

Esto funciona muy bien, ¡gracias! Así es como puedo matar mis solicitudes de larga ejecución. – Emmanuel

3

En Linux ver /etc/oracle/sqlnet.ora,

sqlnet.outbound_connect_timeout= value

también tienen opciones:

tcp.connect_timeout y SQLNET .expire_time, ¡buena suerte!

+0

Creo que esto es para la conexión, no para la ejecución de instrucciones. – Glyph

+0

Es una solución de trabajo, pruébelo;) – BetarU

Cuestiones relacionadas