You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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查询结果:
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 16:54:52