SQLAlchemy ORM操作SQL Server 2022时会话休眠无法提交求助
SQL Server 2022下SQLAlchemy提交无响应排查方案
问题背景
我在使用SQLAlchemy ORM快速入门教程代码时,遇到环境差异问题:在公司的SQL Server 2022数据库上,代码能成功创建表并提交,但插入数据后无法执行COMMIT,脚本无动作且会话处于休眠状态;但相同代码(仅修改连接字符串)在自建的AWS RDS SQL Server实例上运行完全正常,插入后能正常触发COMMIT。
测试代码
from typing import List from typing import Optional from sqlalchemy import ForeignKey from sqlalchemy import String from sqlalchemy.orm import Session from sqlalchemy.orm import DeclarativeBase from sqlalchemy.orm import Mapped from sqlalchemy.orm import mapped_column from sqlalchemy.orm import relationship import engine_creator class Base(DeclarativeBase): pass class User(Base): __tablename__ = "user_account" id: Mapped[int] = mapped_column(primary_key=True) name: Mapped[str] = mapped_column(String(30)) fullname: Mapped[Optional[str]] addresses: Mapped[List["Address"]] = relationship( back_populates="user", cascade="all, delete-orphan" ) class Address(Base): __tablename__ = "address" id: Mapped[int] = mapped_column(primary_key=True) email_address: Mapped[str] user_id: Mapped[int] = mapped_column(ForeignKey("user_account.id")) user: Mapped["User"] = relationship(back_populates="addresses") if __name__ == '__main__': engine = engine_creator.create_engine(echo=True, future=True) Base.metadata.create_all(engine) with Session(engine) as session: spongebob = User( name="spongebob", fullname="Spongebob Squarepants", addresses=[Address(email_address="spongebob@sqlalchemy.org")], ) sandy = User( name="sandy", fullname="Sandy Cheeks", addresses=[ Address(email_address="sandy@sqlalchemy.org"), Address(email_address="sandy@squirrelpower.org"), ], ) patrick = User(name="patrick", fullname="Patrick Star") session.add_all([spongebob, sandy, patrick]) session.commit()
一、开发者可自行尝试的排查操作
- 显式触发事务:在
session.add_all()后手动添加session.begin(),再执行session.commit(),强制开启事务后提交 - 关闭自动刷新:创建Session时禁用自动刷新,改为
with Session(engine, autoflush=False) as session:,避免隐式刷新操作引发的阻塞 - 简化插入逻辑:暂时去掉关联的Address对象,只插入单个User实例,排查是否是级联操作导致的阻塞
- 修正连接字符串参数:显式指定隔离级别为
READ COMMITTED,创建engine时添加参数isolation_level="READ COMMITTED";同时检查是否存在autocommit=True这类干扰参数 - 捕获提交异常:在commit代码块外包裹异常捕获,打印具体错误信息:
try: session.commit() except Exception as e: print(f"提交失败详情:{str(e)}") session.rollback() - 确认引擎类型:检查
engine_creator创建的是同步引擎,避免误用异步引擎导致的代码阻塞
二、请DBA检查的SQL Server配置项
- 默认事务隔离级别:确认数据库默认隔离级别是否为
SERIALIZABLE等过高级别,此类级别易引发锁等待导致会话休眠 - 锁超时设置:查看
LOCK_TIMEOUT参数配置,是否超时时间过长,或存在其他会话持有目标表的未释放锁 - 表级触发器:检查
user_account和address表是否存在插入触发器,触发器内部可能存在死锁或未提交的嵌套事务 - 系统资源瓶颈:排查数据库实例的CPU、内存、磁盘IO是否存在资源耗尽情况,资源不足会导致提交操作无法推进
- 连接池限制:确认数据库的连接池配置,是否存在最大连接数过低导致新请求阻塞的情况
- 分布式事务配置:检查是否开启了MS DTC,若代码意外触发分布式事务,可能因配置问题导致提交停滞
- 审计监控拦截:确认是否有数据库审计、安全监控工具拦截COMMIT语句,或执行前进行了长时间校验
内容的提问来源于stack exchange,提问作者Thomas Vanhelden
相关产品推荐
相关产品推荐

