如何在SqlAlchemy+ibm_db_sa中禁用IBM DB2 for i自动提交?
问题:如何通过ibm_db_sa和SQLAlchemy关闭自动提交?
当前操作的表未开启日志记录,因此必须关闭自动提交(若表开启日志则无需此操作)。
已尝试以下代码:
smt = f"db2+ibm_db://{user}:{password}@{hostname}:{port}/{database};autocommit=0" engine = create_engine(smt, echo=True).execution_options(autocommit=False) sm = sessionmaker(engine, autocommit=False, autoflush=False) with sm.begin() as session: record = User(**user_dict) session.add(record)
但出现报错:
sqlalchemy.exc.ProgrammingError: (ibm_db_dbi.ProgrammingError) ibm_db_dbi::ProgrammingError: Statement Execute Failed: [IBM][CLI Driver][AS] SQL7008N REXX variable "USERSG " contains inconsistent data. SQLSTATE=55019 SQLCODE=-7008
补充说明:
- 设置
autocommit=True时仍出现相同错误 - 尝试将
isolation_level设为AUTOCOMMIT和NONE时,触发如下报错:sqlalchemy.exc.ArgumentError: Invalid value 'AUTOCOMMIT' for isolation_level. Valid isolation levels for ibm_db_sa are RS, UR, CURSOR STABILITY, RR, UNCOMMITTED READ, READ STABILITY, CS, REPEATABLE READ - 使用JDBC连接器关闭自动提交可正常运行,也曾参考相关方案禁用自动提交,但未解决问题。
解决方案
1. 修正连接字符串与引擎配置
ibm_db_sa的连接字符串中,自动提交参数需用autocommit=false(而非0),且创建引擎时直接指定执行选项:
smt = f"db2+ibm_db://{user}:{password}@{hostname}:{port}/{database};autocommit=false" engine = create_engine(smt, echo=True, execution_options={"autocommit": False})
2. 手动控制事务会话
避免使用sm.begin()(会自动提交事务),改为手动管理事务的开启、提交与回滚:
sm = sessionmaker(engine, autoflush=False) session = sm() try: record = User(**user_dict) session.add(record) # 手动提交事务,确保非日志表的数据一致性 session.commit() except Exception as e: session.rollback() raise finally: session.close()
3. 适配ibm_db_sa的隔离级别
ibm_db_sa不支持AUTOCOMMIT或NONE,需从官方支持的级别中选择,默认的CURSOR STABILITY(缩写CS)即可满足需求:
engine = create_engine( smt, echo=True, execution_options={"autocommit": False, "isolation_level": "CS"} )
4. 确认表的日志属性
通过DB2命令验证目标表是否为非日志表:
SELECT TABLE_NAME, LOGGED FROM SYSCAT.TABLES WHERE TABLE_NAME = 'USERSG'
若结果为NOT LOGGED,则必须通过显式事务提交来避免SQL7008N错误,这也是JDBC能正常运行的核心原因——它的事务流程完全适配DB2非日志表的要求。
内容的提问来源于stack exchange,提问作者Wolfeius
相关产品推荐
相关产品推荐

