[英]sqlalchemy: stopping a long-running query
我有一个看似简单的情况,但找不到直接的解决方案。
我正在使用 sqlalchemy 查询 postgres。 如果发生客户端超时,我想停止/取消来自另一个线程的长时间运行的 postgres 查询。 该线程可以访问 Session 或 Connection 对象。
此时我已经尝试过:
session.bind.raw_connection().close()
和
session.connection().close()
和
session.close
和
session.transaction.close()
但是无论我尝试什么,postgres 查询仍然会继续直到它结束。 我是通过在顶部观看 pg 才知道这一点的。 这不是很容易做到吗? 我错过了什么吗? 如果不获取pid并直接发送停止信号,这是不可能的吗?
到目前为止,这似乎运作良好:
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()
在 MYSQL 上发现可以指定查询优化器提示。 一个这样的提示是 MAX_EXECUTION_TIME 指定查询在终止前应该执行多长时间。
您可以在 app.py 中添加它
@event.listens_for(engine, 'before_execute', retval=True)
def intercept(conn, clauseelement, multiparams, params):
from sqlalchemy.sql.selectable import Select
# check if it's select statement
if isinstance(clauseelement, Select):
# 'froms' represents list of tables that statement is querying
table = clauseelement.froms[0]
'''Update the timeout here in ms (1s = 1000ms)'''
timeout_ms = 4000
# adding filter in clause
clauseelement = clauseelement.prefix_with(f"/*+ MAX_EXECUTION_TIME({timeout_ms}) */", dialect="mysql")
return clauseelement, multiparams, params
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.