2012-02-24 4 views
8

나는 직설적 인 상황이지만 직선적 인 해결책을 찾을 수 없습니다.sqlalchemy : 장기 실행 쿼리 중지

저는 postgres를 쿼리하기 위해 sqlalchemy를 사용하고 있습니다. 클라이언트 시간 초과가 발생하면 다른 스레드에서 오래 실행중인 포스트 그레스 쿼리를 중지하거나 취소하고 싶습니다. 스레드는 Session 또는 Connection 객체에 액세스 할 수 있습니다. 내가 해봤이 시점에서

:

session.bind.raw_connection().close() 

session.connection().close() 

session.close 

session.transaction.close() 

하지만 내가 무엇을 시도하든 postgres 쿼리는 끝날 때까지 계속됩니다. 나는 이것을 맨 꼭대기에서 보는 것으로 알고있다. 이것은 상당히 쉬운 일이 아니어야합니까? 나는 뭔가를 놓친거야? 이것은 pid를 얻지 않고 직접 정지 신호를 보내지 않으면 불가능합니까?

+0

당신이 완전히 클라이언트 프로세스를 강제 종료해도, 데이터베이스가 무엇인지에 따라 그 쿼리를 롤백하는 데 시간이 오래 걸릴 수 있습니다 얼마나 많은 데이터가 테이블에 있는지를 나타냅니다. 쿼리를 중단하는 방법을 찾는 대신 쿼리를 최적화하십시오. – wberry

+0

예, 최적화가 가장 중요합니다. 그러나 프로젝트의 특성상 타임 아웃이 발생할 것이므로 모든 기반을 다룰 수 있는지 확인하고 싶습니다. 귀하의 의견에 감사드립니다. –

+0

원시 소켓에 접근하여이를 닫는 방법은 psycopg2 드라이버에 묻힐 것입니다. 이를 찾으려면 소스를 검토해야합니다. sqlalchemy 계층에서 설명 할 수없는 동작과 하드 충돌에 대비하여 실제로 소켓 중 하나를 강제 종료하는 즉시 시작하십시오. – wberry

답변

6

이 지금까지 잘 작동하는 것 같다 :

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