如何为查询执行设置语句超时时间

26
在我的网络应用程序中,一些Postgres SQL查询执行时间很长。我希望只为其中的一部分设置语句超时。
其中一部分查询必须在超时后取消,但其他查询则必须无限制地工作。
在Postgres中存在statement_timeout函数。
如何使用statement_timeout函数包装SqlAlchemy查询?
像这样:
SET statement_timeout TO 1000; -- timeout for one second
<sqlalchemy generated query>;
RESET statement_timeout; -- reset

这对我来说设置查询超时的完美方法:

users = session.query(User).timeout(0.5).all()

SqlAlchemy必须:1)设置语句超时时间 2)执行查询并返回结果 3)为当前会话重置语句超时时间

还有其他设置查询执行超时的方法吗?

更新1. 我的解决方案

我的解决方案是一个自定义连接代理(已使用psycopg2==2.4和SQLAlchemy==0.6.6进行测试):

from sqlalchemy.interfaces import ConnectionProxy

class TimeOutProxy(ConnectionProxy):
    def cursor_execute(self, execute, cursor, statement, parameters, context, executemany):

        timeout = context.execution_options.get('timeout', None)

        if timeout:
            c = cursor._parent.cursor()
            c.execute('SET statement_timeout TO %d;' % int(timeout * 1000))
            c.close()

        return execute(cursor, statement, parameters, context)


engine = create_engine(URL, proxy=TimeOutProxy(), pool_size=1, max_overflow=0)

这个解决方案不需要重置statement_timeout,因为每个SqlAlchemy查询都在隔离事务中执行,并且statement_timeout是在当前事务中定义的。

使用示例(timeout参数以秒为单位):

Session.query(Author).execution_options(timeout=0.001).all()

Session.bind.execute(text('select * from author;') \
      .execution_options(timeout=0.001)) \
      .fetchall()
1个回答

3

1
第一个链接已经失效。 - Vikas Prasad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接