解决mysql连接隔夜失效问题

问题描述

  1. 系统使用hibernate连接数据库;
  2. 启动服务器后,数据库操作正常,但时间超过8小时后,后台访问数据库时总是报错:com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: The last packet successfully received
    from the server was 46,218,269 milliseconds ago. The last packet sent successfully to the
    server was 46,218,270 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.

原因

  • Mysql服务器默认的“wait_timeout”是8小时,也就是说一个connection空闲超过8个小时,Mysql将自动断开该 connection。而hibernate获取连接的时候认为连接池里的这个连接还是有效的,所以就拿来使用,这时候就报错了。

解决办法

url 加参

  • connection url 加参数:&autoReconnect=true

修改数据库连接的超时时间

修改数据库连接的超时时间,这种方式会影响数据库性能,可能会出现大量休眠连接;

参考:http://dwz.cn/5dDEiB

http://dwz.cn/5dFhRQ

  1. 进入mysql,查看变量信息:show variables like '%timeout%'; 结果如下:
Variable_name Value 说明
interactive_timeout 28800 默认为8h
wait_timeout 28800 默认为8h
  1. 修改方式
  • 方式一 运行命令:

    set interactive_timeout=31536000;

    set wait_timeout=31536000;

  • 方式二 打开 **my.ini **文档, 在

    # The TCP/IP Port the MySQL Server will listen on
    port=3306下面添加

    1
    2
    3
    # this is myown dinifition for mysql connection timeout
    wait_timeout=31536000
    interactive_timeout=31536000
  1. 重启mysql服务
  2. 查看修改后的超时时间:show variables like '%timeout%'; 若显示以下结果则表名设置成功:
Variable_name Value 说明
interactive_timeout 31536000 设置超时时间为一年
wait_timeout 31536000 设置超时时间为一年

修改hibernate配置

参考:Hibernate连接数据库超时设置autoReconnect=true http://xupo.iteye.com/blog/901327

  • 用hibernate需添加xml 代码:

    1
    2
    3
    <property name="connection.autoReconnect">true</property>
    <property name="connection.autoReconnectForPools">true</property>
    <property name="connection.is-connection-validation-required">true</property>
  • 如需要用c3p0连接池:

    1
    2
    3
    4
    <property name="hibernate.c3p0.acquire_increment">1</property>  
    <property name="hibernate.c3p0.idle_test_period">0</property>
    <property name="hibernate.c3p0.timeout">0</property>
    <property name="hibernate.c3p0.validate">true</property>

采用c3p0或dbcp管理数据库连接池

  • 在hibernate.cfg.xml中的c3p0链接池的配置中增加下面项:

    参考:Hibernate连接数据库超时设置autoReconnect=true http://xupo.iteye.com/blog/901327

    1
    2
    3
    <property name="c3p0.idle_test_period">120</property>  
    <!-- seconds -->
    <!-- default: 0 -->
  • 在dbcp中我们要处理好以下几个问题:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    <bean id="dataSource"
    class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName"
    value="com.mysql.jdbc.Driver">
    </property>
    <property name="url"
    value="jdbc:mysql://localhost:3306/mylog">
    </property>
    <property name="maxWait" value="20000"> </property>
    <property name="testOnBorrow" value="true"></property>
    <property name="testOnReturn" value="true"></property>
    <property name="testWhileIdle" value="true"></property>
    <property name="validationQuery" value="SELECT 1"></property>
    <property name="timeBetweenEvictionRunsMillis" value="3600000"></property>
    <property name="numTestsPerEvictionRun" value="50"></property>
    <property name="minEvictableIdleTimeMillis" value="120000"></property>
    <property name="removeAbandoned" value="true"/>
    <property name="removeAbandonedTimeout" value="6000000"/>
    <property name="username" value="root"></property>
    <property name="password" value="123456"></property>
    </bean>