mysql连接超时怎么处理

mysql连接超时怎么处理,第1张

MYSQL_OPT_READ_TIMEOUT 是 MySQL c api 客户端中用来设置读取超时时间的参数。在 MySQL 的官方文档中,该参数的描述是这样的:

MYSQL_OPT_READ_TIMEOUT (argument type: unsigned int *)The timeout in seconds for each attempt to read from the server. There are retries if necessary, so the total effective timeout value is three times the option value. You can set the value so that a lost connection can be detected earlier than the TCP/IPClose_Wait_Timeout value of 10 minutes.

也就是说在需要的时候,实际的超时时间会是设定值的 3 倍。但是实际测试后发现实际的超时时间和设置的超时时间一致。

而具体什么时候发生三倍超时,在文档中没有找到。所以对 MySQL 5.7.20 的源码进行了一些分析。

使用 GDB 调试代码找了实际与 mysql server 通信的代码,如下:

请点击输入图片描述

其中 vio_read() 函数中,使用 recv 和 poll 来读取报文和做读取超时。net_should_retry() 函数只有在发生 EINTR 时才会返回 true。从这段代码来看是符合测试结果的,并没有对读取进行三次重试。只有在读取 *** 作被系统中断打断时才会重试,但是这个重试并没有次数限制。

从上面代码的分析可以看出,代码的逻辑和文档的描述不符。于是在一顿搜索后,找到了一个 MySQL 的 BUG(Bug #31163)。该 BUG 报告了在 MySQL 5.0 中,MySQL c api 读取的实际超时时间是设置的三倍,与现有文档描述相符。于是对 MySQL 5.0.96 的代码又进行分析。

同样使用 GDB 找到了通信部分的代码。这次找到了重试三次的代码,如下:

请点击输入图片描述

这个版本的 MySQL api 的读写超时是直接使用的 setsockopt 设置的。第一次循环,在 A 点发生了第一次超时(虽然注释写的非阻塞,但是客户端的连接始终是阻塞模式的)。然后在 B 点将该 socket 设置为阻塞模式,C 点这里重置 retry 次数。由于设置了 alarm 第二次以后的循环会直接进入 D 点的这个分支,并且判断循环次数。作为客户端时net->retry_count 始终是 1,所以重试了两次,共计进行了 3 次 vioread 后从 E 点退出函数。

由上面的分析可知,MySQL 文档对于该参数的描述已经过时,现在的 MYSQL_OPT_READ_TIMEOUT 并不会出现三倍超时的问题。而 Bug #31163 中的处理结果也是将文档中该参数的描述更新为实际读取超时时间是设定时间的三倍。也许是 MySQL 的维护者们在后续版本更新时忘记更新文档吧。

用Fsocket获取数据时能够控制超时的。

如果用

File_get_contents($url)

可以临时设定环境变量:

设定默认socket超时时间

ini_set("default_socket_timeout", 3)养成好习惯,使用fsocket获取数据。

如果使用Curl,也可以在Curl中控制超时时间:

curl_setopt($ch, CURLOPT_TIMEOUT, 15)

PHP中mysql函数是不提供类似mysql超时选项的,但是php.ini的mysql.connect_timeout可设置

Maximum time (in seconds) for connect timeout. -1 means nolimit

mysql.connect_timeout = 60

也可以在php脚本中调用设置ini_set()

最近做的一个JavaWeb项目,持久层用SpringJDBC+DBCP+MySQL。一开始只配置了DBCP的一些常用参数,没有注意对空闲连接的检查和回收。项目部署在tomcat后,刚开始使用没用问题。第二天再试图登录时,发生了报错:

可以看到,报错信息提示上次交互已经是82664635ms前,超过了MySQL server配置的'wait_timeout'(默认是8小时),所以该连接已经被MySQL回收了,但DBCP不知道连接已被回收,依然试图执行 *** 作,引发了异常。报错信息提示可以修改wait_timeout或者添加autoReconnect=true。

(备注:mysql5以上的,设置autoReconnect=true 是无效的 只有4.x版本,起作用)

这两个参数的默认值是8小时(60 60 8=28800)。 注意:wait_timeout的最大值只允许2147483 (24天左右)

也可以用MySQL命令进行修改

这种办法治标不治本。

2.减少连接池内连接的生存周期,使之小于上一项中所设置的wait_timeout 的值。

也就是说,让已经断开的空闲连接没有机会被使用,提前被回收。

以C3P0配置为例:

DBCP中配置minEvictableIdleTimeMillis即可。

3.配置连接池

定期使用连接池内的连接,使得它们不会因为闲置超时而被 MySQL 断开。并且每次使用连接前检查连接是否可用,定期回收空闲的连接。

修改 c3p0 的配置文件,在 Spring 的配置文件中设置:

DBCP连接池的配置:

DBCP官方配置文档: http://commons.apache.org/proper/commons-dbcp/configuration.html

C3P0的配置标准:

关于MySQL的wait_timeout连接超时问题报错解决方案


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/8311605.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-15
下一篇 2023-04-15

发表评论

登录后才能评论

评论列表(0条)

保存