c3p0连接数据库超时问题:The last packet successfully received;The last packet sent successfully to the server

问题描述

java.sql.SQLException: The last packet successfully received from the server was 36,483,780 milliseconds ago.  The last packet sent successfully to the server was 36,483,781 milliseconds ago. is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem. Query: select id,author,sectionName,releaseDate,status,title from article where  title like '%%' and releaseDate between ? AND ? order by releaseDate desc limit ?,? Parameters: [0, 2020-04-19 10:20:13, 0, 10]
	at org.apache.commons.dbutils.AbstractQueryRunner.rethrow(AbstractQueryRunner.java:320)
	at org.apache.commons.dbutils.QueryRunner.query(QueryRunner.java:349)
	at org.apache.commons.dbutils.QueryRunner.query(QueryRunner.java:287)
	at com.wei.dao.impl.ArticleDAOImpl.findByPage(ArticleDAOImpl.java:93)
	at com.wei.service.impl.ArticleServiceImpl.searchAllByCondition(ArticleServiceImpl.java:76)
	at com.wei.web.servlet.ArticleServlet.searchAllByCondition(ArticleServlet.java:150)
	at com.wei.web.servlet.ArticleServlet.doGet(ArticleServlet.java:54)
	at com.wei.web.servlet.ArticleServlet.doPost(ArticleServlet.java:180)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:650)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
	at com.wei.web.filter.EncodingFilter.doFilter(EncodingFilter.java:29)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:218)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
	at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:956)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:442)
	at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1082)
	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:623)
	at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Unknown Source)

c3p0连接数据库超时问题:The last packet successfully received;The last packet sent successfully to the server_第1张图片

翻译一下错误信息

The last packet successfully received from the server was 36,483,780 milliseconds ago. The last packet sent successfully to the server was 36,483,781 milliseconds ago. is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem. Query: select id,author,sectionName,releaseDate,status,title from article where title like '%%' and releaseDate between ? AND ? order by releaseDate desc limit ?,? Parameters: [0, 2020-04-19 10:20:13, 0, 10]

从服务器成功接收到的最后一个数据包是36483780毫秒前。最后一个成功发送到服务器的数据包是36483781毫秒前。比服务器配置的“等待超时”值长。在应用程序中使用之前,应考虑过期和/或测试连接有效性,增加客户端超时的服务器配置值,或使用Connector/J连接属性“autoReconnect=true”来避免此问题。

很容易看出是由于wait_timeout(服务器关闭非交互连接之前等待活动的秒数)造成的。mysql会根据wait_timeout设置每个空闲连接的超时时间,时间到了就会断开。

说明

c3p0连接数据库超时

在用c3p0连接mysql数据库时,时间长了会自动断开,那是因为mysql服务器默认的“wait_timeout”是8小时【也就是默认的值默认是28800秒】,也就是说一个connection空闲超过8个小时,Mysql将自动断开该connection,通俗的讲就是一个连接在8小时内没有活动,就会自动断开该连接。wait timeout的值可以设定,但最多只能是2147483,不能再大了。也就是约24.85天。但是更改wait timeout值治标不治本,所有我们要更改连接池的配置文件。

解决办法

在c3p0连接池的配置文件中加入以下配置代码(根据需要增删):

		 
		<property name="initialPoolSize" value="2"/>
		 
		<property name="minPoolSize" value="2"/>
		   
		<property name="maxPoolSize" value="15"/>
		   
		<property name="acquireIncrement" value="2"/>
		   
        <property name="acquireRetryAttempts" value="0"/>  
           
        <property name="acquireRetryDelay" value="1000" />  
	       
		<property name="maxIdleTime" value="3600"/>
	       
		<property name="maxStatements" value="0"/>
		   
		<property name="maxStatementsPerConnection" value="0"/>
		
		<property name="preferredTestQuery" value="select 1"/>
	    
		<property name="idleConnectionTestPeriod" value="1800"/>
		
		<property name="testConnectionOnCheckout" value="false"/>

这部分参考:https://blog.csdn.net/hui1322157301/article/details/83780353

查看mysql的wait_timeout

show global variables like 'wait_timeout';

c3p0连接数据库超时问题:The last packet successfully received;The last packet sent successfully to the server_第2张图片

默认设置28800秒,即8小时,明显连接时间55,518,630 milliseconds超过了mysql数据库设置的wait_timeout

修改命令:mysql>set global wait_timeout=28800;

C3P0作为连接池,它的最大的任务就是来管理链接的,可是实际上它并不知道这个链接是否还有效,所以,当MySQL某个链接的建立时间已经超过了wait_timeout的时候,那么这个链接实际上已经不能用了。而C3P0却还不知道,相当于C3P0持有了不能使用的链接。

3.问题解决

解决的方法有3种:

  • 增加wait_timeout的时间。
  • 减少Connection pools中connection的lifetime。
  • 测试Connection pools中connection的有效性。
  • JDBC URL上面加一个autoReconnect=true ,在新的connector/J版本里面已经deprecated了,文档里面建议不要使用.

我用的这个

在c3p0连接池的配置文件中加入以下配置代码(根据需要增删):

		 
		<property name="initialPoolSize" value="2"/>
		 
		<property name="minPoolSize" value="2"/>
		   
		<property name="maxPoolSize" value="15"/>
		   
		<property name="acquireIncrement" value="2"/>
		   
        <property name="acquireRetryAttempts" value="0"/>  
           
        <property name="acquireRetryDelay" value="1000" />  
	       
		<property name="maxIdleTime" value="3600"/>
	       
		<property name="maxStatements" value="0"/>
		   
		<property name="maxStatementsPerConnection" value="0"/>
		
		<property name="preferredTestQuery" value="select 1"/>
	    
		<property name="idleConnectionTestPeriod" value="1800"/>
		
		<property name="testConnectionOnCheckout" value="false"/>

这部分参考:https://blog.csdn.net/hui1322157301/article/details/83780353

注意下面的写法与上面参考中的不一样,里面的值的写法,按照他那样写值,我这不起效果

这里最重要的一项是idleConnectionTestPeriod:隔多少秒检查所有连接池中的空闲连接,默认为0表示不检查;看看你的配置是否少了这个配置,这里的秒数一定要小于mysql的全局的超时秒数

show global variables like '%timeout%'; 

最终的c3p0-config.xml文件


<c3p0-config>
	<default-config>
		<property name="user">rootproperty>
		<property name="password">1234property>
		<property name="driverClass">com.mysql.jdbc.Driverproperty>
		<property name="jdbcUrl">jdbc:mysql:///kjxnproperty>
		
		 
		<property name="initialPoolSize">2property>
		 
		<property name="minPoolSize">2property>
		   
		<property name="maxPoolSize">property>
		   
		<property name="acquireIncrement">2property>
		   
        <property name="acquireRetryAttempts">0property>  
           
        <property name="acquireRetryDelay">1000property>  
	       
		<property name="maxIdleTime">3600property>
	       
		<property name="maxStatements">0property>
		   
		<property name="maxStatementsPerConnection">0property>
		
		<property name="preferredTestQuery">select 1property>
	    
		<property name="idleConnectionTestPeriod">1800property>
		
		<property name="testConnectionOnCheckout">falseproperty>
	default-config> 
c3p0-config> 

log中也给了解决方案:

You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem.

简单点概括,在配置C3P0的时候,如果要防止链接失效的情况,可以配置一个testConnectionOnCheckout的属性,当时该属性会比较大的影响性能。

如果比较在意性能的,可以设置testConnectionOnCheckout为false,设置testConnectionOnCheckin为true,设置idleConnectionTestPeriod为30秒

spring中配置数据源

这里参考:https://www.cnblogs.com/xiaosheblog/p/7637612.html
c3p0连接数据库超时问题:The last packet successfully received;The last packet sent successfully to the server_第3张图片
properties文件

在这里插入图片描述
启动项目,通过输出日志可看到,每30秒连接池会自动测试连接了。
在这里插入图片描述

后两种方法显然不太实用

增加mysql数据库的超时时间,由于最大超时时间是2147483一年,不可无限制增加,再说也不应该随便增加。'autoReconnect=true'如果使用的时候reconnect会影响效率,而且据说mysql5以上无效(本人没试),而且官方也不建议
http://bugs.mysql.com/bug.php?id=5020

采用c3p0提供的方案

可参考:http://www.mchange.com/projects/c3p0/index.html#configuring_connection_testing

The most reliable time to test Connections is on check-out. But this is also the most costly choice from a client-performance perspective. Most applications should work quite reliably using a combination of idleConnectionTestPeriod and testConnectionOnCheckin. Both the idle test and the check-in test are performed asynchronously, which can lead to better performance, both perceived and actual. 
 
For some applications, high performance is more important than the risk of an occasional database exception. In its default configuration, c3p0 does no Connection testing at all. Setting a fairly long idleConnectionTestPeriod, and not testing on checkout and check-in at all is an excellent, high-performance approach. 

最可靠的是退出时间测试连接。但这也是最昂贵的从客户端性能的角度选择。大多数应用程序应该使用idleConnectionTestPeriod和testConnectionOnCheckin相当可靠。闲置的测试和登记测试是异步执行的,这可能导致更好的性能,感知和实际。

对于某些应用程序,高性能比偶尔的风险更重要数据库异常。在默认配置中,c3p0没有连接测试。设置一个相当长的idleConnectionTestPeriod,而不是测试是一个很好的检验和登记,高性能的方法。

考虑再三可以如下设置

设置c3p0中连接池内连接的生存周期(idleConnectionTestPeriod)小于数据库中的wait_timeout的值


		<property name="idleConnectionTestPeriod" value="18000"/>

这个解决方案参考:https://blog.csdn.net/honghailiang888/article/details/52691591

修改msyql 配置 ,不推荐

保证应用在MySQL的’wait_timeout’时间内,至少访问一次数据库,配置文件增加心跳检测部分

sys.db.initialSize=10
sys.db.maxIdle=50
sys.db.minIdle=5
sys.db.maxActive=50
sys.db.logAbandoned=true
sys.db.removeAbandoned=true
sys.db.removeAbandonedTimeout=120
sys.db.maxWait=60000
sys.db.type=mysql
dialect=MYSQL
sys.db.class=com.mysql.jdbc.Driver

sys.db.url=jdbc:mysql://localhost:3306/test?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8
sys.db.username=root
sys.db.password=123456

	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
		<property name="driverClassName" value="${sys.db.class}"/>
		<property name="url" value="${sys.db.url}"/>
		<property name="username" value="${sys.db.username}"/>
		<property name="password" value="${sys.db.password}"/> 
		<property name="initialSize" value="${sys.db.initialSize}"/>
		<property name="maxIdle" value="${sys.db.maxIdle}"/>
		<property name="minIdle" value="${sys.db.minIdle}"/>
		<property name="maxActive" value="${sys.db.maxActive}"/>
		<property name="logAbandoned" value="${sys.db.logAbandoned}"/>
		<property name="removeAbandoned" value="${sys.db.removeAbandoned}"/>
		<property name="removeAbandonedTimeout" value="${sys.db.removeAbandonedTimeout}"/>
		<property name="maxWait" value="${sys.db.maxWait}"/>
		
		
		
		<value>truevalue>property>
		<value>falsevalue>property>
		<value>falsevalue>property>
		<value>select 1value>property>
		<value>1value>property>
		<value>28700value>property>
		<value>${sys.db.maxActive}value>property>
		<value>18000000value>property>
		
	bean>

这部分参考:https://blog.csdn.net/u014755645/article/details/85160430

你可能感兴趣的:(mysql,后端)