SQLAlchemy执行TRUNCATE后关闭Session,SQL Server查询仍持续运行
问题:Python脚本执行TRUNCATE后SQL Server会话仍长时间运行
我编写了一段用于截断SQL Server表的Python脚本,代码如下:
# 创建连接 from sqlalchemy.engine import URL,create_engine from sqlalchemy.sql import text from sqlalchemy.orm import sessionmaker connection_url = URL.create( "mssql+pyodbc", # username="", # password="", host="SERVER NAME", # port=, database="DB NAME", query={ "driver": "SQL Server Native Client 11.0", "TrustServerCertificate": "yes", # "authentication": "ActiveDirectoryIntegrated", }, ) # 截断表 engine = create_engine(connection_url) Session = sessionmaker(bind=engine) session = Session() try: session.execute(text('''TRUNCATE TABLE [dbo].[MyTable]''')) session.commit() except Exception as e: print("an error occured:", e) finally: session.close()
脚本执行后看似正常,但在SQL Server上运行sp_whoisactive查询时,发现3个多小时后该TRUNCATE语句仍处于运行状态。我无法理解为何关闭Session后查询还会持续运行?
sp_whoisactive查询结果:
可能的原因及解决办法
- 锁阻塞:TRUNCATE需要获取表的排他锁,如果该表被其他会话占用(比如存在未提交的事务、长时运行的查询正在读取该表),就会进入等待状态。可以通过查询
sys.dm_tran_locks和sys.dm_os_waiting_tasks查看具体的阻塞源。 - 事务提交异常:代码中调用了
session.commit(),但如果提交过程中出现网络波动、数据库端隐性错误,可能导致事务未真正完成,会话挂起。建议在代码中增加提交后的日志输出,同时检查SQL Server的事务日志确认状态。 - 连接池未释放资源:
session.close()仅关闭ORM会话,但底层数据库连接可能被SQLAlchemy的连接池保留。可以在finally块中添加engine.dispose(),强制销毁连接池中的所有连接,确保资源释放。 - 表依赖或数据量问题:如果表存在外键依赖、大量关联索引,或者数据量极大,TRUNCATE可能耗时较长,但3小时属于异常情况,优先排查锁阻塞问题。
修改后的脚本示例
# 创建连接 from sqlalchemy.engine import URL, create_engine from sqlalchemy.sql import text from sqlalchemy.orm import sessionmaker connection_url = URL.create( "mssql+pyodbc", # username="", # password="", host="SERVER NAME", # port=, database="DB NAME", query={ "driver": "SQL Server Native Client 11.0", "TrustServerCertificate": "yes", # "authentication": "ActiveDirectoryIntegrated", }, ) # 截断表 engine = create_engine(connection_url) Session = sessionmaker(bind=engine) session = Session() try: print("开始执行TRUNCATE操作") session.execute(text('TRUNCATE TABLE [dbo].[MyTable]')) print("TRUNCATE执行完成,提交事务") session.commit() print("事务提交成功") except Exception as e: print("发生错误:", e) session.rollback() # 出错时主动回滚事务 finally: session.close() engine.dispose() # 销毁连接池所有连接 print("会话及数据库连接已关闭")
内容的提问来源于stack exchange,提问作者jmich738
相关产品推荐
相关产品推荐

