Snowflake存储过程执行报错:Scoped事务未完成被回滚求助
问题排查与解决方案
1. 先修复参数不匹配问题
从报错SQL能看到末尾多了一个逗号:
call expraction_process(%(batch_id)s, %(job_name)s, %(job_status)s, %(data_source_id)s, )
这是因为你传递的参数数量和存储过程预期不匹配:
change方法定义只接收4个业务参数,但测试调用传了5个- 导致生成的SQL语法错误,触发后续事务异常
修正方式:
要么调整change方法签名,补上第五个参数并更新存储过程调用语句:
def change(self, id, name, status, data, extra_param): query = "call extraction_process(:b_id, :na, :status_1, :data_source, :extra)" values = {'b_id': id, 'na': name, 'status_1': status, 'data_source': data, 'extra': extra_param} self.execute_query(query, values, with_result=False)
要么减少测试调用的参数数量,和方法定义保持一致。
2. 调整事务处理逻辑
你的会话配置了autocommit=True,但execute_query里又手动调用session.commit(),这会导致事务冲突:
autocommit=True时,每个execute()都会自动提交事务- 手动
commit()会尝试提交已结束的事务,干扰Snowflake存储过程的内部事务管理
修复方案二选一:
选项A:保留autocommit,移除手动commit
def execute_query(self, query, values=None, with_result=True): session = None result = "No result" try: session = self.get_session() output = session.execute(query, values) if with_result: result = output.fetchall() # 移除手动commit,依赖autocommit自动提交 return result except Exception as e: if session: session.rollback() raise e finally: if session: self.close_session(session)
选项B:关闭autocommit,手动管理事务(更推荐)
# 修改Database类的sessionmaker配置 Session = sessionmaker(bind=cls.db_conn, autocommit=False, autoflush=False) cls.session_maker = scoped_session(Session) # execute_query保持现有commit/rollback逻辑即可
3. 检查存储过程内部实现
报错核心信息Scoped transaction started in stored procedure is incomplete and it was rolled back,说明存储过程本身未正确结束事务:
- 如果存储过程里手动开启了事务(用
BEGIN),必须确保有对应的COMMIT或ROLLBACK语句 - 执行DML的存储过程不需要手动开事务,但要保证没有未处理的异常导致事务中断
4. 验证会话关闭逻辑
确保close_session方法正确清理会话,避免连接池出现异常连接:
def close_session(self, session): if session: session.close() Database.session_maker.remove() # 清理scoped_session的线程绑定会话
总结
优先解决参数不匹配和事务冲突问题,这两个是触发当前报错的直接原因。如果问题仍存在,重点检查Snowflake存储过程的事务处理逻辑。
内容的提问来源于stack exchange,提问作者develop
相关产品推荐
相关产品推荐

