SqlAlchemy执行Insert无报错日志触发自动回滚问题咨询
SqlAlchemy Insert操作无报错自动回滚问题解决
问题成因
该自动回滚是SqlAlchemy 2.0+版本默认事务规则导致,与SQL语法、表结构无直接关联:
- 调用
engine.connect()获取连接时,框架会自动开启隐式事务,对应日志里的BEGIN (implicit)记录。 engine.connect()对应的上下文管理器默认不提供自动提交能力,当with块执行结束、连接归还连接池时,若未检测到手动提交的事务,会自动执行ROLLBACK回滚所有未持久化的写操作。- 该行为属于框架预设的事务管理逻辑,不属于SQL执行错误,因此不会抛出业务异常,仅能通过echo开启的执行日志看到最终的回滚记录。
修复方案
两种写法均可解决自动回滚问题,按需选择即可:
- 方案1:手动提交事务
执行插入语句后显式调用commit方法提交事务,代码修改如下:stmt = NiceSchools.insert().values(id = 1, name = 'Fábio', Safety_Score = 80, Location = 'Saúde') with engine.connect() as conn: conn.execute(stmt) conn.commit() # 手动提交后事务持久化,不会被自动回滚 - 方案2:使用自动事务上下文
将engine.connect()替换为engine.begin(),该上下文管理器会在代码块无异常执行完成后自动提交事务,块内抛出异常时自动回滚,无需手动编写commit逻辑:stmt = NiceSchools.insert().values(id = 1, name = 'Fábio', Safety_Score = 80, Location = 'Saúde') with engine.begin() as conn: conn.execute(stmt) # 退出with块时自动完成事务提交
附带代码隐患修正
表结构中Start_date字段的默认值写法存在逻辑问题:
Column('Start_date', DateTime, default = datetime.today())
上述写法会在Table类定义加载的瞬间执行一次datetime.today()生成固定时间值,后续所有插入操作如果不传该字段,都会复用这个固定的初始时间,而非插入时刻的实时时间。修复方式为去掉括号,传入函数引用,让框架在插入执行时动态调用生成时间:
Column('Start_date', DateTime, default = datetime.today)
如果需要使用数据库服务端的当前时间,也可以替换为SqlAlchemy内置函数default=func.now()。
内容的提问来源于stack exchange,提问作者FábioRB
相关产品推荐
相关产品推荐

