最近的项目中,发现Mysql数据库在8个小时内,没有请求时,会自动断开连接,这是MySQL服务器的问题。

原因: The last packet successfully received from the server was 1,836,166 milliseconds ago.  The last packet sent successfully to the server was 29,134 milliseconds ago.


MySQL服务器默认的“wait_timeout”是28800秒即8小时,意味着如果一个连接的空闲时间超过8个小时,MySQL将自动断开该连接,

而连接池却认为该连接还是有效的(因为并未校验连接的有效性),当应用申请使用该连接时,就会导致上面的报错。


解决方案:
数据库连接如果空闲时,进行有效性验证。(如果使用连接池,配置几个属性即可)

<!-- 解决数据库8小时内无请求自动断开,连接失败问题 -->
    <property name="testOnBorrow" value="true"></property>
    <property name="testOnReturn" value="true"></property>
    <property name="testWhileIdle" value="true"></property>
    <property name="validationQuery" value="SELECT 1 FROM DUAL"></property>

Oracle数据库:SELECT 1 FROM DUAL

SqlServer数据库:SELECT 1

下面以DBCP连接池举例——

(其他连接池应该也都有以下属性,可以查看文档或源码),下图是我的项目的连接池的源码举例:



在DBCP连接池中有以下几个属性:


testOnBorrow、testOnReturn、testWhileIdle ,他们的意思是当是取得连接、返回连接或连接空闲时是否进行有效性验证(即是否还和数据库连通的),默认都为false。所以当数据库连接因为某种原因断掉后,再从连接池中取得的连接,实际上可能是无效的连接了,所以,为了确保取得的连接是有效的,可以把把这些属性设为true。当进行校验时,需要另一个参数:validationQuery,对oracle来说,可以是:SELECT COUNT(*) FROM DUAL,实际上就是个简单的SQL语句,验证时,就是把这个SQL语句在数据库上跑一下而已,如果连接正常的,当然就有结果返回了。

然后 minEvictableIdleTimeMillis 配合 timeBetweenEvictionRunsMillis ,每过timeBetweenEvictionRunsMillis秒对连接池进行一次检测,将对象闲置时间超过minEvictableIdleTimeMillis秒的对象进行销毁,创建新的对象来取代。这样就能保证时刻都有正常的连接池对象存在。

还有其他的一些参数,可以参考源代码。
部分参数简要说明:
removeAbandoned :是否自动回收超时连接
removeAbandonedTimeout:超时时间(以秒数为单位)
removeAbandoned=true那么在getNumActive()快要到getMaxActive()的时候,系统会进行无效的Connection的回收,回收的Connection为removeAbandonedTimeout(默认300秒)中设置的秒数后没有使用的Connection
logAbandoned:logAbandoned=true的话,将会在回收事件后,在log中打印出回收Connection的错误信息,包括在哪个地方用了Connection却忘记关闭了,在调试的时候很有用。
maxWait:超时等待时间以毫秒为单位
maxIdle:最大空闲连接
minIdle:最小空闲连接
maxActive:最大连接数
testOnBorrow、testOnReturn、testWhileIdle、validationQuery:上面有介绍
另外很重要的一点是每次连接使用完了不要忘了调用connection.close()使连接返回到连接池

解决这个问题的办法有三种: 1. 增加 MySQL 的 wait_timeout 属性的值。 修改 /etc/ mysql /my.cnf文件,在 [ mysql d] 节中设置: # Set a connection to wait 8hours in idle status. wait_timeout =86400 相关参数,红色部分 mysql > show variables like ‘%timeout%’; +————————–+——-+ | Variable_name | Value | +————————–+——-+ | connect_timeout | 5 | | delayed_i
专家解答: MySQL 是一个小型关系型 数据库 管理系统,由于 MySQL 体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,许多中小型网站为了降低网站总体拥有成本而选择了 MySQL 作为网站 数据库 。   关于mysq
你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客:撤销:Ctrl/Command + Z 重做:Ctrl/Command + Y 加粗:Ctrl/Command + B 斜体:Ctrl/Command + I 标题:Ctrl/Command + S
最近做的一个JavaWeb项目,持久层用SpringJDBC+DBCP+ MySQL 。一开始只配置了DBCP的一些常用参数,没有注意对空闲 连接 的检查和回收。项目部署在tomcat后,刚开始使用没用问题。第二天再试图登录时,发生了报错: HTTP Status 500 - Request processing failed; nested exception is org.springfr...
mysql 在启动后,如果一段时间内没有活动,那么将 自动 关闭该 连接 。这段时间,默认为8 小时 。在spring+hibernate中解决该问题,应该使用proxool这个 连接 池来代替DBCP的 连接 池。因为DBCP 连接 池没有 自动 重连功能。修改applicationContext.xml: <bean id="dataSource" class="org.logicalco...
之前就遇到过这种 mysql 创建链接8 小时 未访问 断开 的问题。当时解决了,但是没有记录。结果今天部署一个自己的项目又出现了这种问题,所以这次记录下来,防止以后再遇到。 前提:后台使用的是jdbc进行的 连接 。 问题排查: 部署服务后,由于使用人数不多,所以 mysql 的访问比较少。经过了一晚上之后,在访问就提示如下的错误: com. mysql .jdbc.Communication***ception: Communications link failure due to underlying
连接 MySQL 数据库 ,您需要使用PHP的 MySQL 扩展程序。在PHP 8中, MySQL 扩展已经被移除了,取而代之的是 mysql i和PDO扩展。这里我们演示使用 mysql i扩展 连接 MySQL 数据库 的方法。 1. 首先,您需要安装并启动 MySQL 服务器,并创建一个 数据库 和一个用户,以便您可以在PHP中使用它们。 2. 在PHP中,您可以使用 mysql i扩展来 连接 MySQL 数据库 。以下是一个简单的示例: ```php // 数据库 连接 参数 $servername = "localhost"; $username = "username"; $password = "password"; $dbname = "database_name"; // 创建 连接 $conn = new mysql i($servername, $username, $password, $dbname); // 检查 连接 是否成功 if ($conn->connect_error) { die(" 连接 失败: " . $conn->connect_error); } else { echo " 连接 成功!"; 在此示例中,我们使用了 mysql i构造函数来创建一个 连接 对象,并传递了 MySQL 服务器的 连接 参数。如果 连接 失败,我们使用die()函数打印错误信息并停止脚本的执行。否则,我们将打印“ 连接 成功!”消息。 3. 连接 成功后,您可以使用 mysql i对象的方法来执行各种操作,例如查询、插入、更新和删除数据。以下是一个简单的示例: ```php // 查询数据 $sql = "SELECT * FROM table_name"; $result = $conn->query($sql); // 输出查询结果 if ($result->num_rows > 0) { while($row = $result->fetch_assoc()) { echo "id: " . $row["id"]. " - Name: " . $row["name"]. "<br>"; } else { echo "0 结果"; // 关闭 连接 $conn->close(); 在此示例中,我们使用 mysql i的query()方法执行一个查询,并使用fetch_assoc()方法从结果集中获取每一行的数据。最后,我们关闭 连接 对象。 这是一个简单的PHP 8 连接 MySQL 数据库 的例子。您可以根据自己的需求进行更改和扩展。