Docker中Python3应用连接Oracle时遇ORA-25408错误的原因排查
ORA-25408: can not safely replay call 错误诱因分析
环境信息
- Python3 应用运行在 Docker 容器中
- 使用 Oracle 厚客户端(Client Shared Library 64-bit - 21.13.0.0.0)
- 通过 TNS 连接 Oracle 19.0.0 版本数据库
- TNS 配置:
DB = (description= (address = (host = 10.1.1.2)(protocol = tcp)(port = 1521)) (address = (host = 10.1.1.3)(protocol = tcp)(port = 1521)) (failover = yes) (connect_data = (service_name = DB) (failover_mode = (type = select) (method = basic) ) ) )
报错信息
Traceback (most recent call last): File "/usr/local/lib/python3.10/site-packages/flask/app.py", line 1463, in wsgi_app response = self.full_dispatch_request() File "/usr/local/lib/python3.10/site-packages/flask/app.py", line 872, in full_dispatch_request rv = self.handle_user_exception(e) File "/usr/local/lib/python3.10/site-packages/flask/app.py", line 870, in full_dispatch_request rv = self.dispatch_request() File "/usr/local/lib/python3.10/site-packages/flask/app.py", line 855, in dispatch_request return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return] File "/app/mtu_service.py", line 45, in tracking_history change_read_status(recipient_id, mailing_id) File "/app/db_service.py", line 89, in change_read_status cursor.execute(sql, [first_id, second_id]) File "/usr/local/lib/python3.10/site-packages/oracledb/cursor.py", line 383, in execute impl.execute(self) File "src/oracledb/impl/thick/cursor.pyx", line 243, in oracledb.thick_impl.ThickCursorImpl.execute File "src/oracledb/impl/thick/utils.pyx", line 431, in oracledb.thick_impl._raise_from_odpi File "src/oracledb/impl/thick/utils.pyx", line 421, in oracledb.thick_impl._raise_from_info oracledb.exceptions.DatabaseError: ORA-25408: can not safely replay call
可能诱因
- 故障转移后的操作复用:TNS配置启用了
basic模式的select类型故障转移,当主节点故障切换到备节点时,原有会话会被中断。如果应用未检测到会话失效,继续执行之前未完成的数据库操作(如本次的cursor.execute),Oracle无法安全重放已中断的调用,就会触发该错误。 - 会话状态不一致:故障转移后,备节点上新会话的事务上下文、绑定变量、游标状态等无法与原主节点会话完全同步,此时复用原有连接执行操作会导致状态冲突,引发报错。
- 跨版本兼容性问题:使用21.13版本的厚客户端连接19.0.0版本数据库,虽然整体兼容,但部分故障转移相关的逻辑可能存在版本适配缺陷,导致重放逻辑异常。
- 连接池失效连接复用:若应用使用连接池,长时间闲置的连接可能因数据库节点切换已失效,但连接池未检测到这种状态变化,应用取出失效连接执行操作时就会出现该错误。
内容的提问来源于stack exchange,提问作者Alex K
相关产品推荐
相关产品推荐

