解决一个数据库连接造成后台卡死的问题
前段时间写了一个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之类的语句,表创建之后不需要手动进行修改。
记下来以备忘。
上一篇: Kafka Exactly-Once 之事务性实现
下一篇: Ajax+Spring实现文件上传
推荐阅读
-
完美解决MySQL通过localhost无法连接数据库的问题
-
解决MSSQL2005远程连接sql2000非默认端口数据库的问题
-
MSSQL数据库占用内存过大造成服务器死机问题的解决方法
-
MFC连接数据库时,无法启动程序,计算机丢失libmysql.dll的问题解决办法
-
oracle数据库查询没问题,正常显示两个汉字;但是java后台Hibernate查询的时候只显示第一个汉字怎么解决?
-
ASP 包含文件中的路径问题和使用单一数据库连接文件的解决方案
-
Linux中无法远程连接数据库问题的解决方法
-
win7系统安装2个mysql版本后连接不上数据库的问题如何解决?
-
Django数据库连接丢失问题的解决方法
-
Android Studio 提示“你的主机中的软件中止了一个已建立的连接”问题解决方法