[英]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.