使用druid数据源,由于网络问题导致oracle SocketInputStream.socketRead0堵塞解决办法

线上Oracle数据库网络非常不稳定,不时发生连接闪断,发现一个线程一直堵塞,日志没有错误。dump出线程信息后如下:

pool-4-thread-50" prio=10 tid=0x00007f92f5251000 nid=0x26e1 runnable [0x00007f929a1df000]

   java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:152)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at oracle.net.ns.Packet.receive(Packet.java:282)
at oracle.net.ns.DataPacket.receive(DataPacket.java:103)
at oracle.net.ns.NetInputStream.getNextPacket(NetInputStream.java:230)
at oracle.net.ns.NetInputStream.read(NetInputStream.java:175)
at oracle.net.ns.NetInputStream.read(NetInputStream.java:100)
at oracle.net.ns.NetInputStream.read(NetInputStream.java:85)
at oracle.jdbc.driver.T4CSocketInputStreamWrapper.readNextPacket(T4CSocketInputStreamWrapper.java:122)
at oracle.jdbc.driver.T4CSocketInputStreamWrapper.read(T4CSocketInputStreamWrapper.java:78)
at oracle.jdbc.driver.T4CMAREngine.unmarshalUB1(T4CMAREngine.java:1179)
at oracle.jdbc.driver.T4CMAREngine.unmarshalSB1(T4CMAREngine.java:1155)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:279)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:186)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:521)
at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:194)
at oracle.jdbc.driver.T4CStatement.executeForDescribe(T4CStatement.java:853)
at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1145)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1259)
at oracle.jdbc.driver.OracleStatement.executeQuery(OracleStatement.java:1469)
- locked <0x000000074abc5ae8> (a oracle.jdbc.driver.T4CConnection)
at oracle.jdbc.driver.OracleStatementWrapper.executeQuery(OracleStatementWrapper.java:389)
at com.alibaba.druid.pool.vendor.OracleValidConnectionChecker.isValidConnection(OracleValidConnectionChecker.java:84)
at com.alibaba.druid.pool.DruidAbstractDataSource.testConnectionInternal(DruidAbstractDataSource.java:1358)
at com.alibaba.druid.pool.DruidDataSource.getConnectionDirect(DruidDataSource.java:1260)

由于网络不稳定,每次拿连接的时候先测试连接的可用性,但是发生了socket 读堵塞。阻塞了线程的运行。是查询超时没有设置,我立即查看DruidDataSource配置是否有查询超时配置。发现如下三个配置

datasource.setValidationQueryTimeout(queryTimeout);
datasource.setQueryTimeout(queryTimeout);
datasource.setTransactionQueryTimeout(queryTimeout);
重新添加配置后重启,继续观察。隔几天再次发现还是堵塞。判断 这些查询超时的配置不能设置到Socket的读超时设置中。查看资料发现需要配置如下属性

datasource.connectionProperties=oracle.jdbc.ReadTimeout=10000;oracle.net.CONNECT_TIMEOUT=10000
参考资料:https://www.jianshu.com/p/6d19e0d7f81c

https://www.cubrid.org/blog/understanding-jdbc-internals-and-timeout-configuration

资料里面有详细的解读。

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在Spring项目中使用阿里巴巴的Druid连接池来装载Oracle数据源,可以按照以下步骤进行: 1. 首先,在pom.xml文件中添加DruidOracle驱动的依赖: ``` <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.6</version> </dependency> <dependency> <groupId>com.oracle.jdbc</groupId> <artifactId>ojdbc8</artifactId> <version>19.7.0.0</version> </dependency> ``` 2. 在Spring配置文件中配置数据源: ``` <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/> <property name="url" value="jdbc:oracle:thin:@localhost:1521:ORCL"/> <property name="username" value="your_username"/> <property name="password" value="your_password"/> <property name="initialSize" value="5"/> <property name="maxActive" value="50"/> <property name="minIdle" value="5"/> <property name="maxWait" value="60000"/> <property name="validationQuery" value="SELECT 1 FROM DUAL"/> <property name="testWhileIdle" value="true"/> <property name="timeBetweenEvictionRunsMillis" value="60000"/> <property name="minEvictableIdleTimeMillis" value="300000"/> <property name="poolPreparedStatements" value="true"/> <property name="maxPoolPreparedStatementPerConnectionSize" value="20"/> </bean> ``` 其中,initialSize是连接池启动时创建的初始化连接数;maxActive是连接池最大连接数;minIdle是连接池最小连接数;maxWait是获取连接的最大等待时间;validationQuery是用来检测连接是否有效的SQL语句;testWhileIdle是空闲时是否进行连接检测;timeBetweenEvictionRunsMillis是定时检查连接池中空闲连接的间隔时间;minEvictableIdleTimeMillis是连接池中连接最小空闲时间;poolPreparedStatements是是否缓存PreparedStatement;maxPoolPreparedStatementPerConnectionSize是单个连接池中最大的缓存Statement数目。 3. 在DAO层中使用数据源: ``` @Repository public class UserDaoImpl implements UserDao { @Autowired private DataSource dataSource; private JdbcTemplate jdbcTemplate; @PostConstruct public void init() { jdbcTemplate = new JdbcTemplate(dataSource); } // ... } ``` 在DAO实现类中通过@Autowired注入Druid数据源,并在@PostConstruct注解的init()方法中创建JdbcTemplate对象,即可使用数据源进行数据库操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值