Azure SQL数据库pyodbc超时后connection.close阻塞10分钟如何解决?
问题:查询超时后
conn.close()等待过久,如何实现预期退出行为? 我执行了以下包含超时查询的Python代码:
import pyodbc TIMEOUT_SEC = 1 QUERY_DELAY_SEC = TIMEOUT_SEC + 1 DSN = ".." QUERY = f"WAITFOR DELAY '00:00:{QUERY_DELAY_SEC:02d}';SELECT 1;" conn = pyodbc.connect(DSN) conn.timeout = TIMEOUT_SEC cursor = conn.cursor() try: result = cursor.execute(QUERY).fetchall() cursor.close() except Exception as error: print(error) finally: # 若发生超时异常,此close操作会等待约10分钟 # 若查询成功(例如移除`WAITFOR DELAY`),close操作会立即完成 conn.close(); print(f"{result=}")
预期行为:
- 抛出超时错误
- 打印错误信息
- 立即退出脚本
实际行为:
- 抛出超时错误
- 打印错误信息
- 等待约10分钟后才退出脚本
- 最终退出脚本
能否强制实现预期的行为?
解决办法
方案1:开启连接自动提交
在创建连接时设置autocommit=True,让每个查询都作为独立事务执行。超时后无需等待事务回滚,conn.close()会立即完成:
conn = pyodbc.connect(DSN, autocommit=True)
方案2:强制断开ODBC连接句柄
如果无法开启自动提交,可以通过调用ODBC底层API直接终止连接,跳过默认的等待逻辑:
import pyodbc import ctypes # ... 原有代码 ... except Exception as error: print(error) # 获取连接的ODBC句柄并强制断开 handle = conn.handle() ctypes.windll.odbc32.SQLDisconnect(handle) finally: conn.close()
方案3:用线程控制查询超时
把查询逻辑放到子线程中,主线程设置超时时间,超时后直接终止线程并关闭连接:
import pyodbc import threading TIMEOUT_SEC = 1 QUERY_DELAY_SEC = TIMEOUT_SEC + 1 DSN = ".." QUERY = f"WAITFOR DELAY '00:00:{QUERY_DELAY_SEC:02d}';SELECT 1;" result = None error_info = None def run_query(conn): global result, error_info cursor = conn.cursor() try: result = cursor.execute(QUERY).fetchall() cursor.close() except Exception as e: error_info = e conn = pyodbc.connect(DSN) conn.timeout = TIMEOUT_SEC query_thread = threading.Thread(target=run_query, args=(conn,)) query_thread.start() query_thread.join(TIMEOUT_SEC) if query_thread.is_alive(): print("查询超时,已强制终止连接") else: if error_info: print(error_info) else: print(f"{result=}") conn.close()
内容的提问来源于stack exchange,提问作者xliiv
相关产品推荐
相关产品推荐

