欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

解决一个数据库连接造成后台卡死的问题

程序员文章站 2022-03-07 20:29:07
...

 

      前段时间写了一个Demo项目,客户端通过网络连接,访问netty实现的一个后台获取数据。

 

      虽然后台netty的工作任务也是通过线程池来完成相应的任务处理,但是偶现客户端在读取数据时,读取的线程给卡住,读不到数据,并且只是偶尔出现,试过了很多次,每次在观察的时候都没有重现,甚至有压力测试都没有出现过,本地Debug也没有任务问题,通过每一步加日志,发现任务加到线程池之后最终并没有执行,线程池满掉了,开始怀凝是不是某一步出现了死锁,再仔细检查几轮代码,都没有什么点可能出死锁。

 

      多次出现问题之后,发现有一个规律:“往往出问题的时候,长时间没有访问后台,然后再去访问的时候比起平常访问更容易出现”

 

       由以上规律猜测,可能是后台的某个资源被释放或者因为过期失效,而用到的资源又只有数据库,spring配的C3P0的数据库连接池。查看配置文件:

 

 

 

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" 
         destroy-method="close">
        <property name="driverClass" value="com.mysql.jdbc.Driver"/>
	<property name="jdbcUrl" value="jdbc:mysql://xx.xx.xx.xx/xxx"/>
	<property name="user" value="xxx"/>
	<property name="password" value="xxx"/>
	<property name="minPoolSize" value="1"/>
	<property name="maxPoolSize" value="20"/>
	<property name="checkoutTimeout" value="10000"/>
	<property name="maxStatementsPerConnection" value="50"/>
	<property name="testConnectionOnCheckout" value="true"/>
</bean>

 

 

配置中连接checkout是有检查的,超时也不长,按道理应该是没有问题的啊

仔细看了这参数的解释,testConnectionOnCheckout是在checkout的时候,通过对数据进行一次查询或者JDBC4以上和C3P00.9.5以后会去调用isValid() 来检查,原理都可以理解为对数据库进行一次最简单的查询。

然后也查到mysql在长时间没使用的连接,是会出现卡死的现象,也就是idle状态,联想到之前过出现C++访问Mysql也有这种问题,最后自己写了个线程,隔段时间做一次简单查询来解决,实际上我的这种情况很在checkout的时候就已经卡死,而又不是连接超时,也不是checkout超市,再看了下C3P0的参数配置,还有一个idleConnectionTestPeriod,这个就是定时去“激活”一下闲置的连接,加上之后,万事大吉,问题再也没有出现过了。另个还有一个参数官方也建议加上,配合使用,最终配置如下:

 

 

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
	<property name="driverClass" value="com.mysql.jdbc.Driver"/><!-- 203.195.235.154 119.29.178.28-->
	<property name="jdbcUrl" value="jdbc:mysql://xx.xx.xx.xx/xxx"/>
	<property name="user" value="xxxxx"/>
	<property name="password" value="xxxx"/>
	<property name="minPoolSize" value="1"/>
	<property name="maxPoolSize" value="20"/>
	<property name="checkoutTimeout" value="10000"/>
	<property name="maxStatementsPerConnection" value="50"/>
	<property name="automaticTestTable" value="pooltest"/>
	<property name="testConnectionOnCheckout" value="true"/>
	<property name="testConnectionOnCheckin" value="true"/>
	<property name="idleConnectionTestPeriod" value="60"/>
</bean>

 

 

       automaticTestTable,这是可选,表示连接池做测试的时候,访问的一个表名,会自动创建,执行select 1之类的语句,表创建之后不需要手动进行修改。

 

 

记下来以备忘。