【问题记录】Cause: java.sql.SQLRecoverableException: No more data to read from socket
异常说明:
当Oracle客户端(应用)接收数据库服务器发送的数据时,它会从套接字中读取数据。如果在读取数据的过程中,套接字中没有更多的数据可供读取,那么Oracle客户端就会报告“没有更多数据从套接字读取”错误。
常见原因:
应用使用了连接池,当从连接池取得的connection失效或者超时的时候,使用这个连接来进行数据库操作就会抛出以上异常;
客户端和服务器之间的网络连接存在问题,导致数据传输中断;
数据库服务器上的某个进程崩溃或异常终止,导致无法提供数据;
查询结果集非常庞大,导致传输数据的套接字缓冲区已满;
触发了低版本Oracle的bug
排查方法:
开启连接池的TestQuery(ValidationQuery)等测试连接可用性的配置,检查关闭空闲长连接的配置max_idle_time(客户端空闲连接可用性检查间隔要小于此值),减少空闲连接数。
检查网络连接:确保客户端和服务器之间的网络连接正常。 联系网络管理员查看并确认网络警告日志(拦截或关闭长连接等)。
如果数据库服务器上的某个进程崩溃或终止导致错误发生,联系数据库管理员查找数据库服务的异常警告日志,查看相关线索(killsession)。
增加套接字缓冲区大小:如果查询结果集非常庞大,可以尝试增加传输数据的套接字缓冲区大小。可以通过调整操作系统的TCP缓冲区大小参数来实现。例如,在Linux系统中,可以使用sysctl命令来修改参数。
优化查询语句:如果查询结果集非常庞大,可以考虑优化查询语句以减小结果集的大小。可以使用合适的索引、分页查询或其他方法来限制结果集的大小。
Oracle 11.2.0.4以下版本,可以尝试关闭绑定变量窥探的隐藏参数试试:_optim_peek_user_binds = false
问题解决:
联系项目数据库运维人员反馈,出问题的项目Oracle版本为12.2.xxx,同时项目设置了max_idle_time=10(分钟)默认值为0,而应用端使用druid连接池的testWhileIdle=true 、 timeBetweenEvictionRunsMillis=900000
经验证通过调整应用端druid timeBetweenEvictionRunsMillis=300000 或修改服务器 max_idle_time=20,都可以解决。
另外,联想到之前也遇到过MySQL环境偶发的 Cause: java.sql.SQLException: Connection is closed 问题,是否也是相同的原因导致呢。
参考资料:
https://blog.51cto.com/u_16112859/6277609
https://developer.aliyun.com/article/286959
https://blog.csdn.net/cyzl5/article/details/106262365
https://www.cnblogs.com/lightdb/p/9580463.html
https://blog.csdn.net/Mr_Runner/article/details/118964470