事情的起因:

某项目的开发同学突然Q我们组的某同学,要求我们调整MySQL的连接等待超时参数wait_timeout。要求我们从28800s调整到31536000s(也就是一年)

应用端测试环境的tomcat报错日志如下图:

恩。报错很明显。这个问题百度后的解决方案大部分都是要求数据库端更改连接等待超时时间。那么这种解决方法是否可行呢?

遗憾的是,这是不可行的。

主要原因还是性能考量。Wait_timeout参数的含义是指MySQL将断开指定时间内没有任何操作的连接(Connection)。这个值会直接影响到MySQL数据库的并发性能,因为Connection是由参数max_connections设置的。

在高并发场景中,由于我们的连接数已经封顶,过长的wait_timeout值会导致连接长时间不释放(如像开发同学提出修改为一年)。如果开发人员没有在代码中显式关闭连接,或者使用连接池时没有定义连接回收方式,那么连接数将会随时间递增,最后达到参数max_connections的设定值后,报经典的1040错误,too many connections...

所以为了避免出现这种情况,DBAs的立场是非常明确的,绝对不允许轻易修改生产环境数据库的参数。这个原因我后面给出。那么现在我们继续focus到眼前的问题。

既然不允许更改数据库参数,但是问题还在,那么如何定位问题的真正原因呢?这里我将根据我在处理这个问题时的思路,引导大家掌握基本的排障方法。

问题定位:

连接出现问题,那么肯定要涉及到两个主要的部分:数据库和webserver的应用连接池。由于出于对自己工作的过度自信(笑),所以针对webserver端我问了开发同学几个问题:

1. 是否使用了连接池?如果不是,是否有在代码里显式关闭连接?

2. 连接池是否配置了连接自动回收机制(如tomcat的话可能要涉及removeAbandoned和removeAbandonedTimeout等参数)?

开发同学给出的答案是:

1. 确实使用了连接池(dbcp原生的)。

2. 经过和运维相关同学协调,发现tomcat里确实缺少连接回收的参数。

解决方案:

OK,那么我基本可以定位问题了,下面就是给出解决方案:

1. Tomcat增加removeAbandoned=true、removeAbandonedTimeout=60、testOnBorrow=true和validationQuery=select now()。目的是让webserver的连接池自己在连接前先判断数据库侧是否已经将连接释放掉,如果释放掉则会回收并重建连接。注:removeAbandoned和removeAbandonedTimeout两个参数我在给出时略有犹豫,因为这两个参数可能会导致连接在removeAbandonedTimeout所设置的时间内没有处理完时,也会被连接池强制回收,从而导致请求没有返回数据就断开了。所以一般生产环境中不会设置这两个参数,不过在得知是测试环境后,我决定先尝试一下看是否能定位问题就是连接池。

2. 如果上述方法不能解决,那么可以尝试更换c3p0这样的第三方连接池。

3. 如果更换c3p0还不能解决,那么请检查综测环境里的这台机器是否开启了防火墙,或者是否selinux的策略有问题。这样做主要是我发现错误日志中的连接断开时间非常有规律。如下图:

因此,可能是某种机制导致人为断开连接。所以在前两种方法都不能解决的情况下,可以尝试使用tcpdump等工具抓包,检查当前系统网络环境。

经过一番痛苦的尝试,终于在更换了c3p0的第三方连接池后,一切都正常了。

后记:

这个小故事,我总结了下面几点请大家借鉴:

1. 所有你看到的故障只是它在某一时间段的某一表象。那么怎么根据这些表象迅速定位问题呢?除了工作经验的积累外,还要掌握把分散的知识点联系起来的能力。这在处理故障时会大有用处。

2. 开发人员不要轻易要求DBA修改数据库。包括参数、数据等等等等。前文提到不允许轻易修改生产数据库的参数,这也是我在每次分享时都要强调的。数据是一个公司的核心,数据库是存放这一核心的工具。数据库最大的特点是稳定,也最需要稳定。不管前端应用开发的多么花里胡哨,实现了多么复杂的逻辑,如果数据库没有稳定支撑,而是在不断变动,那么应用只会出现展现数据不正确(错误数据)或者数据不一致(脏数据)的情况。所以烦请开发同学们对每次提给数据库组的请求一定要慎之又慎。

能在数据库之前就有解决方案的,就绝对不要放到数据库上做。

3. 尽可能的多了解自己工作之外的世界。做技术要有刨根问底的精神,多了解些和本职工作无关的,甚至是其他人的本质工作,你会发现你的职业道路会越走越宽~

PS:

MySQL的Connection Pool和Thread Pool之间的关系

很多人会混淆这两个概念。在one-thread-per-connection的传统配置里,连接和线程就是1对1的关系。但是在thread pool的概念提出后,这种情况就不再是这样的了。这里我用不是DBA就能看懂的语言简单的解释一下:

连接池实现在Client端。由于Client端频繁的创建和释放连接会增加请求的平均响应时间,因此Client端往往会预先创建一些连接,通过这些连接来完成针对数据库的所有请求。在Client端请求繁忙时,还可以通过请求排队机制,缓解数据库并发压力。

线程池实现在Server端(数据库端)。线程池和连接池有点类似,MySQL也会在线程池中预先分配相应的线程资源。除了能完成像连接池一样的功能,如线程复用、请求队列等,还在逻辑上将one-thread-per-connection中的1对1的关系转变为多对1。MySQL的线程池会分为多个group,每个group中会fork出一个或多个worker线程。对于Client端连接池发起的每个连接(socket连接),并不会独占线程池的一个worker线程,而是一个worker线程会处理多个连接。如下图:

不知道这样解释,你明白了吗?

应用端连接MySQL数据库报Communications link failure的更多相关文章

  1. SSH项目过一段时间之后再访问会报一次Could not open Hibernate session for transaction 异常,Caused by: com.mysql.jdbc.CommunicationsException: Communications link failure due to underlyi,再重新方法即可访问成功(通常出现在过了一晚之后再去访问系统)

    前端时间到客户那去进行项目的上线测试,将项目部署好之后,运行都是正常的,可是每到了第二天早上访问的时候,就会报一个Could not open Hibernate session for transa ...

  2. 解决MySQL连接超时Communications link failure due to underlying exception

    最近在用一个MySQL的Java连接池的过程中,连接一晚上不释放,第二天就会造成超时的错误,查了一下原因,原来是因为MySQL默认的空闲等待时间是8个小时,一旦空闲超过8个小时,就会抛出异常.异常文本 ...

  3. 解决mysql连接异常—-com.mysql.jdbc.CommunicationsException: Communications link failure due to underlying exception

    DBCP连接池连接MySql数据库时,一奇葩数据库设置为30秒内无请求自动断开.超时后链接无法关闭,活动链接数飞奔,最后挂掉. 网上找了一圈,一般是这三种,方法一pass,方法二测试无效可能设置错了吧 ...

  4. 解决mysql连接报“Communications link failure”错误

    <!--定义在从数据库获取新连接失败后重复尝试的次数.默认值: 30 :小于等于0表示无限次--> <property name="acquireRetryAttempts ...

  5. com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure 数据库报错

    -- 查询mysql 数据库链接空闲时间持有最大空闲时间,单位为秒 SHOW VARIABLES WHERE VAriable_name = 'interactive_timeout'; -- 会出现 ...

  6. 解决Java程序连接mysql数据库出现CommunicationsException: Communications link failure错误的问题

    一.背景 最近在家里捣鼓一个公司自己搭建的demo的时候,发现程序一启动就会出现CommunicationsException: Communications link failure错误,经过一番排 ...

  7. Java连接MySQL报错:CommunicationsException: Communications link failure

    现象: 报错:Exception in thread "main" com.mysql.cj.jdbc.exceptions.CommunicationsException: Co ...

  8. 【Azure 应用服务】App Service 无法连接到Azure MySQL服务,报错:com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure

    问题描述 App Service使用jdbc连接MySQL服务,出现大量的  Communications link failure: com.mysql.cj.jdbc.exceptions.Com ...

  9. jdbc 连接mysql Communications link failure的解决办法

    使用Connector/J连接MySQL数据库,程序运行较长时间后就会报以下错误: Communications link failure,The last packet successfully r ...

随机推荐

  1. FindResource () RT_HTML 为什么总是出错呢 ?

    #include <windows.h> #include <commdlg.h> #include <ole2.h> BOOL GetHtmlResource(L ...

  2. 牛客第二场 J farm

    White Rabbit has a rectangular farmland of n*m. In each of the grid there is a kind of plant. The pl ...

  3. MySQL:数据表基本操作

    数据表基本操作 注意点: 1.数据表中已经有数据时,轻易修改数据类型,有可能因为不同的数据类型的数据在机器 中存储的方式及长度并不相同,修改数据类型可能会影响到数据表中已有的数据类型. 2.  数据表 ...

  4. Android:如何获取屏幕的宽高

    WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE); DisplayMet ...

  5. mysql基础查询语法

    一.mysql查询的五种子句 where子句(条件查询):按照“条件表达式”指定的条件进行查询. group by子句(分组):按照“属性名”指定的字段进行分组.group by子句通常和count( ...

  6. 50_流程控制函数-case结构

    case函数的使用一:switch case 的效果 /* Java中 switch(变量或表达式){ case 常量1:语句1:break: ... default:语句n;break; } MyS ...

  7. YUM仓库配置

    YUM的前身是YUP(Yellow dog Updater,Yellow dog Linux的软件更新器),最初由TSS公司(Terra Soft Solutions,INC.)使用Python语言开 ...

  8. Java学习笔记22(List接口)

    List接口继承自Collection接口,自身具有三大特点: 1.有序集合:存入和取出的顺序一致: 2.此接口的用户可以对每个元素插入位置进行精确控制:可以通过索引操作元素 3.可以存储重复元素 L ...

  9. ngxinx 配置

    vim 复制操作 1.复制 1)单行复制 在命令模式下,将光标移动到将要复制的行处,按“yy”进行复制: 2)多行复制 在命令模式下,将光标移动到将要复制的首行处,按“nyy”复制n行: 其中n为1. ...

  10. 3--Python入门--Python数据集合类型--元组

    在基础数据类型的基础上,Python有6中数据集合的类型: 列表list,最常用的数据类型,以[]为标识 元组tuple,和list很相似,但是不能二次赋值,用()标识 集合set,和list类似,但 ...