配置sqlnet.ora超时后Oracle Instant Client结合ODPI-C生成core dump问题咨询
排查与解决思路
1. 确认根因触发条件
你现在的崩溃栈是在调用OCISessionGet从客户端连接池获取会话的过程中,触发了pthread_mutex_lock的非法地址错误,属于Oracle Instant Client内部的竞态问题:设置过短的全局网络超时后,超时中断会打断客户端内部的会话分配流程,导致内部结构体状态异常,锁对象还未初始化或者已经被释放就尝试加锁,最终触发段错误。
你可以先在测试环境调整SQLNET.RECV_TIMEOUT和SQLNET.OUTBOUND_CONNECT_TIMEOUT的数值到5s以上,如果崩溃概率大幅下降或者完全消失,就可以确认是短全局超时触发了客户端bug。
2. 优先调整超时配置逻辑
不建议用sqlnet.ora的全局网络超时控制业务操作时长,全局超时会作用在客户端所有网络交互阶段,包括连接池内部保活、会话获取的底层请求,很容易干扰客户端内部的正常逻辑。
你完全可以在ODPI-C和应用层面控制超时:
- 连接获取超时你已经配置了
pool-session-get-timeout,可以直接满足连接获取的超时要求 - 单个SQL执行超时可以调用ODPI-C的
dpiStmt_setTimeout()接口设置,仅作用于业务SQL执行阶段,不会影响客户端内部逻辑 - 移除sqlnet.ora中的两个超时参数,即可立即避免当前的崩溃问题
如果需要数据库侧兜底,也可以给业务用户配置profile,限制单SQL最大执行时长,效果和sqlnet超时一致,不会触发客户端崩溃。
3. 版本升级验证
19.11版本的Instant Client确实存在多个短超时场景下的OCISessionGet崩溃bug,19.12及之后的RU版本已经修复了这类竞态问题。如果你必须保留全局sqlnet超时配置,可以先在测试环境升级到19c最新的Instant Client RU版本(和Oracle 11.2数据库完全兼容),模拟高频获取连接、数据库侧慢响应触发超时的场景,持续压测24小时无崩溃即可在生产升级。
临时规避方案
如果暂时无法升级客户端,直接移除sqlnet.ora中的SQLNET.RECV_TIMEOUT和SQLNET.OUTBOUND_CONNECT_TIMEOUT配置,改用ODPI-C语句超时+业务层超时兜底,即可解决当前的core dump问题,同时满足业务的超时要求。
内容的提问来源于stack exchange,提问作者quidstone

