2012-02-24 15 views
8

Mam pozornie prostą sytuację, ale nie mogę znaleźć prostego rozwiązania.sqlalchemy: zatrzymanie długo działającego zapytania

Używam sqlalchemy do zapytania postgres. Jeśli wystąpi przekroczenie limitu czasu klienta, chciałbym zatrzymać/anulować długo działające zapytania postgresowe z innego wątku. Wątek ma dostęp do obiektu Session lub Connection.

W tym momencie próbowałem:

session.bind.raw_connection().close() 

i

session.connection().close() 

i

session.close 

i

session.transaction.close() 

Ale bez względu na to, co próbuję, zapytanie postgresowe trwa do końca. Wiem to od oglądania pg w górę. Czy nie powinno to być dość łatwe do zrobienia? Brak mi czegoś? Czy nie jest to możliwe bez otrzymania pid i wysłania sygnału stopu bezpośrednio?

+0

Nawet jeśli zabijesz proces klienta w całości, baza danych może zająć dużo czasu, aby wycofać swoje zapytanie, w zależności od tego, co jest i ile danych znajduje się w tabeli. Pracuj nad optymalizacją zapytań, zamiast próbować dowiedzieć się, jak je przerwać. – wberry

+0

Tak, optymalizacja jest najważniejsza, ale ze względu na charakter naszych projektów mają nastąpić limity czasowe i chcemy się upewnić, że obejmujemy wszystkie bazy. Dzięki za komentarz. –

+0

Sposób dostępu do surowego gniazda, aby go zamknąć, zostanie zakopany gdzieś w sterowniku psycopg2. Aby to znaleźć, musisz przejrzeć źródło. Bądź w pełni przygotowany na niewytłumaczalne zachowanie i twarde awarie w warstwie sqlalchemy, zaczynając od momentu, w którym faktycznie wymusisz zamknięcie jednego z gniazd. – wberry

Odpowiedz

6

To wydaje się działać dobrze, do tej pory:

def test_close_connection(self): 
    import threading 
    from psycopg2.extensions import QueryCanceledError 
    from sqlalchemy.exc import DBAPIError 

    session = Session() 
    conn = session.connection() 
    sql = self.get_raw_sql_for_long_query() 

    seconds = 5 
    t = threading.Timer(seconds, conn.connection.cancel) 
    t.start() 

    try: 
     conn.execute(sql) 
    except DBAPIError, e: 
     if type(e.orig) == QueryCanceledError: 
      print 'Long running query was cancelled.' 
    t.cancel() 

source

Powiązane problemy