2012-02-24 83 views
8

我有一个看似简单的情况,但找不到直接的解决方案。sqlalchemy:停止长时间运行的查询

我正在使用sqlalchemy来查询postgres。如果发生客户端超时,我想停止/取消来自另一个线程的长时间运行的postgres查询。该线程可以访问Session或Connection对象。

在这一点上我已经试过:

session.bind.raw_connection().close() 

session.connection().close() 

session.close 

session.transaction.close() 

但无论我尝试什么,postgres查询仍会继续,直到它结束。我从顶级看pg知道这一点。这不是很容易做到吗?我错过了什么?没有获得pid并直接发送停止信号,这是不可能的吗?

+0

即使你完全杀死你的客户端程序,数据库可能需要很长的时间来回滚其查询,这取决于它是和表中有多少数据。致力于优化您的查询,而不是试图找出如何中止它们。 – wberry 2012-02-24 20:47:50

+0

是的,优化是最重要的,但由于我们的项目超时的性质将会发生,我们希望确保我们覆盖所有的基地。谢谢你的评论。 – 2012-02-24 20:58:49

+0

访问原始套接字以关闭它的方式将被埋在psycopg2驱动程序的某处。您必须查看它的来源才能找到它。在sqlalchemy层面为无法解释的行为和严重崩溃做好充分的准备,开始实际强制关闭其中一个套接字的瞬间。 – wberry 2012-02-24 21:02:59

回答

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