mysql连接池不能回避的wait timeout问题(转)
起因
我们的项目组一直在使用albianj作为开发框架在开发应用。使用至今倒也是没有出现很大的问题,但最近加过监控的接口基本上都会在使用一段时间后,突然之间执行数据库操作变得很慢。虽然会变慢,但持续的时间比较短,一般1分钟左右,然后会自动恢复正常。但是过了一段时间,这个现象又会出现,周而复始。从监控看,发生的时间点并无规律,有的时候一天发生3次,有的也会有4-5次。虽然从规律上并无法去查找,那就只能从别的地方想办法:增加一些详细的日志,从日志上看一下问题所在。
详细日志版本刚刚上去,立刻就发生问题了。如下图:

看一下左下角的曲线图,突然飙高,然后在1500ms的高位不下来。经过查找日志(PS:sorry。写文章的时候日志已经被自动清除,没法截图了),发现程序卡在了getConnection这个方法上,并且卡住的时间从60s开始越来越长。
分析
getConnection是一个synchronized方法,主要是从连接池中获取数据连接!卡住时间越来越长这个现象倒是很简单就可以解释:因为getConnection是synchronized的,所以所有的线程到getConnection的时候全部等待,等待的时间越长当然时间越长了。关键在于为啥卡住呢?
当时有两种可能的想法:
- 连接池设置的太小,连接在使用的时候来不及被返还,导致了积压;
- 连接池的设置有问题,返回的连接有问题。如果是这个问题,那可能会比较难查;
第一种情况显然不会存在,查看albianj的数据库配置,所有的配置对于连接池的设置MinSize为5,MaxSize为20.对于我们的应用来说肯定是够用的。那么就是第二个问题了。
首先检查连接复用问题,对于数据库的连接字符串,我已经增加了重连的设置:
autoReconnect=true&failOverReadOnly=false&zeroDateTimeBehavior=convertToNull&maxReconnect=3&autoReconnectForPools=true
显然autoReconnect没有起作用。查了一下mysql的客户端说明,后背发凉。基本上的大意翻译过来是这样的“即使在创建Mysql时url中加入了autoReconnect=true参数,一但这个连接两次访问数据库的时间超出了服务器端wait_timeout的时间限制,还是会CommunicationsException: The last packet successfully received from the server was xxx milliseconds ago. ”。赶快去查一下日志,发现并没有报这个错误。那应该不是这个问题。
既然不能重连接,那么最大的可能就是“返回的连接本来可能就是有问题的,但是程序确认为没有问题”。发生这种问题的最大可能应该就是:数据库连接池的连接过期时间大于mysql的wait_timeut设置。查了一下代码,发现我们默认的数据库连接池连接过期时间是300-30=270s。再去问一下DBA木木,让他查一下线上的数据库wait_timeout设置,被告知是180.瞬间懵逼:连接池的生命周期时间远远参与真实的连接生命周期时间。
原因是找到了,但是这个问题其实前一段时间已经发现并且已经改过了。因为去年我记得很清楚:又一次我们的probactor(job调度系统)报了上文提到的CommunicationsException异常,后来找到了问题就是因为程序对于连接池中连接的alivetime长于数据库的wait timeout设置,随后我千叮咛万嘱咐这个设置必须要小心小心再小心,但这次还是中招了。因为连接池和网络的问题,我们有同事直接放弃连接池,改用每次连接数据库。放弃连接池确实能解决连接不会出现问题,但是侧面也导致了wait_timeout被设置的过小了。但其实只要把连接池中连接的过期时间设置的比wait_timeout小一些就完全可以了。
经过更改后的程序终于恢复了正常,看一下更改后的效果:

科普
何为wait_timeout?
wait_timeout是mysql的一个设置,主要是用来断开不使用的数据库连接。当连接空闲的时间达到wait_timeout设置的最大值时,mysql会主动切断这个连接,以供别的客户端连接数据库。这个值一般是28800,也就是8小时。在mysql中可以通过:
show variables like “%timeout%”;
获取。
另外,当数据库主动切断连接的时候,java的mysql客户端并不知道这个连接已经被切断,所以程序并不知道其已经无效了,然后加上mysql的客户端不支持ReConnect,双重的问题叠加在一起就导致了连接池返回无效连接的可能。这是一个比较扯淡也是一个比较难以发现的问题,但是它确确实实的存在了。大家一定要多加注意。
这个值可以根据自己网络的环境和业务的并发性来调整。
mysql连接池不能回避的wait timeout问题(转)的更多相关文章
- 用swoole简单实现MySQL连接池
MySQL连接池 在传统的网站开发中,比如LNMP模式,由Nginx的master进程接收请求然后分给多个worker进程,每个worker进程再链接php-fpm的master进程,php-fpm再 ...
- 实现一个协程版mysql连接池
实现一个协程版的mysql连接池,该连接池支持自动创建最小连接数,自动检测mysql健康:基于swoole的chanel. 最近事情忙,心态也有点不积极.技术倒是没有落下,只是越来越不想写博客了.想到 ...
- Swoole MySQL 连接池的实现
目录 概述 代码 扩展 小结 概述 这是关于 Swoole 入门学习的第八篇文章:Swoole MySQL 连接池的实现. 第七篇:Swoole RPC 的实现 第六篇:Swoole 整合成一个小框架 ...
- 如何在 Swoole 中优雅的实现 MySQL 连接池
如何在 Swoole 中优雅的实现 MySQL 连接池 一.为什么需要连接池 ? 数据库连接池指的是程序和数据库之间保持一定数量的连接不断开, 并且各个请求的连接可以相互复用, 减少重复连接数据库带来 ...
- 转 Swoole】用swoole简单实现MySQL连接池
MySQL连接池 在传统的网站开发中,比如LNMP模式,由Nginx的master进程接收请求然后分给多个worker进程,每个worker进程再链接php-fpm的master进程,php-fpm再 ...
- 解决Mysql连接池被关闭 ,hibernate尝试连接不能连接的问题。 (默认mysql连接池可以访问的时间为8小时,如果超过8小时没有连接,mysql会自动关闭连接池。系统发布第二天访问链接关闭问题。
解决Mysql连接池被关闭 ,hibernate尝试连接不能连接的问题. (默认MySQL连接池可以访问的时间为8小时,如果超过8小时没有连接,mysql会自动关闭连接池. 所以系统发布第二天访问会 ...
- Java Mysql连接池配置和案例分析--超时异常和处理
前言: 最近在开发服务的时候, 发现服务只要一段时间不用, 下次首次访问总是失败. 该问题影响虽不大, 但终究影响用户体验. 观察日志后发现, mysql连接因长时间空闲而被关闭, 使用时没有死链检测 ...
- MySQL连接池
1. using System; using System.Collections; using MySql.Data.MySqlClient; namespace Helper { /// < ...
- tomcat中使用mysql连接池的配置
1.下载相应的jar包,添加到工程中 需要下载的包主要有commons-pool2-2.2 commons-dbcp2-2.0.1-src commons-dbcp2-2.0.1 commons-c ...
随机推荐
- 【QT】QPixmap和QImage在QLabel显示一张图像
#include <QPixmap> void Dialog::on_Button1_clicked() { QPixmap img; img.load("1.bmp" ...
- js中的hasOwnProperty
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Linux驱动技术(六) _内核中断
在硬件上,中断源可以通过中断控制器向CPU提交中断,进而引发中断处理程序的执行,不过这种硬件中断体系每一种CPU都不一样,而Linux作为操作系统,需要同时支持这些中断体系,如此一来,Linux中就提 ...
- TestLink汉化操作
实验环境版本 xampp-windows-x64-7.3.2-0-VC15-installer + testlink-1.9.19 汉化操作如下 打开testlink的配置文件F:\xampp\htd ...
- url自动补全index.php
location / { index index.html index.htm index.php l.php; autoindex on; if (!-e $request_filename) { ...
- 学习vue 2.x源码笔记
1.响应式原理: 核心:Object.defineProperty,用法如下: var obj1 = {}; var initValue = 'hello'; Object.definePropert ...
- 怎么给button设置背景颜色?【Android】
怎么给button设置背景颜色?[Android] 怎么给button设置背景颜色?[Android] 现在我想给按钮添加背景颜色,怎么做 1.android:background="@an ...
- ELK之使用kafka作为消息队列收集日志
参考:https://www.cnblogs.com/fengjian2016/p/5841556.html https://www.cnblogs.com/hei12138/p/7805475 ...
- Django中,ajax检测注册用户信息是否可用?
ajax检测注册用户信息主体思路 1.在settings.py中配置需要使用的信息 #对static文件进行配置 STATICFILES_DIRS=[ os.path.join(BASE_DIR,'s ...
- cc2640 细节展示
1. 对于 cc2640内部有两个单片机,一个m3负责内核,另一个是一个16位单片机,应该是msp430可以替代主机完成一些数据采集,adc采集,iic等等功能,传感器软件内部可以进行外设配置,并使用 ...