赞
踩
系统异常问题:Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: The last packet successfully received from the server was 93,627,505 milliseconds ago. The last packet sent successfully to the server was 93,627,505 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.
在spring项目中,如果我们用dbcp做数据库连接池,系统会经常莫名其妙报以上的数据库连接异常问题。重新发起一次请求又没问题了。这个异常的出现都是很随机的,想打断点调试都没法调试,网上查过很多资料提到的解决办法都是添加'autoReconnect=true' 配置,或者修改mysql的配置,实际都不能解决问题。这是为什么呢?其实问题的根源就是mysql的wait_timeout这项配置,这项配置定义了mysql数据库连接空闲超时时间,超过这个时间mysql数据库会自动断开空闲连接。而问题就出在这里,当mysql数据库因为连接空闲超时而自动断开连接时,dbcp连接池并没有得到通知,dbcp本身也没有主动检测连接池中的各个连接是否失效的机制,这就导致mysql数据库服务端将这个空闲连接断开了dbcp连接池的客户端对象都不知道,还认为被断开的连接还是正常可用的,这时如果系统发起请求访问数据库,dbcp连接池就会直接把实际已断开连接的空闲连接分派给这个请求任务,这时系统就会报出以上的数据库连接异常。
知道这个原因之后,怎么解决呢?有两个方向:1、修改mysql的wait_timeout空闲超时时间。将这个时间配置得尽可能大,但是这又会带来另一个问题,会产生大量的空闲连接没有被回收,浪费服务器大量的cpu和内存资源。2、让dbcp连接池在mysql服务端空闲超时之前主动断开空闲连接。但是翻遍了dbcp连接池所有配置参数都没有找到能实现这个目标的。怎么办呢?dbcp连接池不行,我们就找其他的替代连接池,c3p0连接池就是其中不错的选择。c3p0连接池有如下两个配置参数:
maxIdleTime:连接最大空闲时间,超出这个空闲时间,连接池就会主动断开这个空闲连接。这恰恰就是我们要解决问题需要的参数。只要这个maxIdleTime 小于 mysql的wait_timeout,就能确保客户端连接池在mysql服务端断开连接之前主动断开空闲连接,就不会出现上述的问题。
idleConnectionTestPeriod:每隔多少秒测试空闲连接,为0时表示不做测试,默认值为0。要实现maxIdleTime超时主动断开空闲连接,就要有一个定时检测机制,而这个参数就是规定每间隔多长时间检测一次空闲连接是否超时的时间间隔参数。两个参数配合起来,就能很好解决问题。
经过以上的分析调研,我们得出结论,要解决这个异常问题,我们需要将 dbcp 连接池换成c3p0 连接池,并根据实际情况,对 maxIdleTime 和 idleConnectionTestPeriod 参数进行合理的配置。c3p0更多的参数配置这里就不展开说了,大家可以网上搜一下。
以下是整合c3p0连接池需要依赖的jar包和关键的配置:
- <!-- c3p0数据库连接池依赖jar包 -->
- <dependency>
- <groupId>com.mchange</groupId>
- <artifactId>c3p0</artifactId>
- <version>0.9.5.5</version>
- </dependency>
- <dependency>
- <groupId>mysql</groupId>
- <artifactId>mysql-connector-java</artifactId>
- <version>5.1.49</version>
- </dependency>
- <!-- 数据库连接池c3p0 -->
- <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
- <property name="driverClass" value="com.mysql.jdbc.Driver" />
-
- <!-- 本地数据库 -->
- <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/your_db_name?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&useSSL=false"></property>
- <property name="user" value="root" />
- <property name="password" value="123456" />
-
-
- <!--初始化连接数 取值要在minPoolSize和maxPoolSize之间(可包含,闭区间) 默认值:3 -->
- <property name="initialPoolSize" value="3" />
- <!-- 最大连接数 (连接池中的连接数不能超过maxPoolSize最大连接数) 默认值:15 -->
- <property name="maxPoolSize" value="100" />
- <!--最小连接数 默认值:3 -->
- <property name="minPoolSize" value="3" />
- <!-- c3p0连接池中数据连接不够时(无空闲连接可用),一次增长的个数(增长不能超过maxPoolSize最大连接个数) 默认值:3 -->
- <property name="acquireIncrement" value="3" />
- <!-- 连接的最大空闲时间,如果超过这个时间还没有被使用,就断开这个连接(设置为0或负数,就永远都不会被断开,这里设置10分钟) 单位:秒 默认值 :0 -->
- <property name="maxIdleTime" value="60" />
- <!-- 每隔多少秒检查所有连接池中的空闲连接 单位:秒 默认值:0 (检查的时候,将所有连接空闲等待时间归零)-->
- <property name="idleConnectionTestPeriod" value="10" />
- <!-- 从数据库获取新连接失败后重复尝试的次数。小于等于0表示无限次 默认值: 30 -->
- <property name="acquireRetryAttempts" value="30" />
- <!-- 两次连接的中间间隔时间(重新尝试的时间间隔) 单位:毫秒 默认值:1000 -->
- <property name="acquireRetryDelay" value="1000" />
- <!-- 连接关闭时,是否将所有未提交的操作进行事务回滚, 默认值:false -->
- <property name="autoCommitOnClose" value="false" />
- <!-- 当连接池用完时,客户端调用getConnection()后等待获取新连接的时间 单位:毫秒 默认值:0 如果值设为 0,将无限期等待,直到有空闲连接。
- 否则按照设置的值,超时将抛出SQLException异常 时间设置过小时会出现连接超时,这样会抛出SQLException异常,设置时间时需要小心,按照实际情况设置适当的值 -->
- <property name="checkoutTimeout" value="0" />
- </bean>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。