如何解决The last packet successfully received from the server was x milliseconds ago异常问题?

系统异常问题: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&amp;characterEncoding=UTF-8&amp;zeroDateTimeBehavior=convertToNull&amp;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>
  • 19
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL报错"The last packet successfully received from the server was X milliseconds ago"时,这通常是由于连接超时引起的。解决这个问题的方法有以下几种: 1. 检查网络连接:首先确保网络连接正常,可以尝试使用其他网络连接或者重启网络设备。 2. 调整连接超时时间:可以通过修改MySQL配置文件中的"wait_timeout"参数来增加连接超时时间。该参数表示MySQL服务器在没有活动连接的情况下等待的时间,默认为8小时。可以将其增加到更大的值,例如设置为28800(8小时)。 3. 优化查询性能:如果查询语句执行时间过长,可能会导致连接超时。可以通过优化查询语句、创建索引、调整数据库结构等方式来提高查询性能,减少连接超时的可能性。 4. 增加服务器资源:如果服务器资源不足,可能会导致连接超时。可以考虑增加服务器的内存、CPU等资源,以提高服务器的处理能力。 5. 使用长连接:长连接是指在一个连接上可以执行多个查询,而不是每次查询都建立一个新的连接。使用长连接可以减少连接建立和断开的开销,降低连接超时的可能性。 6. 检查防火墙设置:有时防火墙设置可能会导致连接超时。确保防火墙没有阻止MySQL服务器的访问。 希望以上方法能够帮助您解决MySQL报错"The last packet successfully received from the server was X milliseconds ago"的问题

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值