事情的起因:

某项目的开发同学突然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. 异常 No module named 'numpy.core._multiarray_umath

    No module named 'numpy.core._multiarray_umath 解决方法: 1. 可能是由于模型保存时出错,导致模型没有保存成功,此时删掉保存的模型即可 2. numpy版 ...

  2. 软件工程项目程序:WC

    1:代码来源:http://yuncode.net/code/c_5087c8e4cd77190 2:Platform:Eclipse Language:Java 3:Bug:暂时没有 4. Func ...

  3. 启动和停止mysql的正确姿势

    1.如果是用脚本起的.那就用脚本停 2.最好用mysql_safe起,mysqladmin -uroot -p shutdown -S /tmp/mysql.sock停 mysqld_safe --d ...

  4. ChinaCock界面控件介绍-CCButton

    即将发布的ChinaCock新版本,将带来一个CCButton控件,实现可视按钮.Delphi原生的Button,在上面滑动后,当释放手指时会误触发OnClick事件,这不是我们想要的结果,CCBut ...

  5. ionic的actionsheet安卓样式不正常的坑及解决之道

    这是actionsheet该有的样子,可是android下变成了这样: 百度后,发现修改lonic.css,注释这段代码就可以了:

  6. 将python环境打包成.txt文件

    1 导出Python环境安装包[root@bogon ~]# pip freeze > packages.txt这将会创建一个 packages.txt文件,其中包含了当前环境中所有包及各自的版 ...

  7. os.path和sys.path的区别

    os.path是module,包含了各种处理长文件名(路径名)的函数. sys.path是由目录名构成的列表,python从中查找扩展模块(python源模块)编译模块,或者二进制扩展),启动pyth ...

  8. python 时间格式化

    2018-10-25 17:49:51 监控软件 原始 2018-10-2517:49:51 切割后 2018/10/25 17:49:51 格式化后 shijian = ' '.join(respo ...

  9. Proxy --概述篇

    概述: Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(meta programming),即对编程语言进行编程. Proxy 可以理解成,在目标对象之前架设 ...

  10. undefined is not an object (evaluating '_react2.PropTypes.string')

    对所引用的组件原 .import React, {Component,PropTypes} from 'react' 改成:import React, {Component} from 'react' ...