问题:

进程启动后,线程数迅速上升至最小线程数后,缓慢上升(线程池限制)到数千,然后由于线程过多,CPU飙升到90%。

对外表现为Api无响应或连接超时。

背景

有些数据存在于另一个机房,通过内网专线连接。一个服务程序有4个数据库,其中3个在本地机房,1个在外地。

各种排查,没有解决。

最终的处理方法

Dump进程

  1. 使用进程管理器,创建进程Dump文件。
  2. 使用VisualStudio打开该Dump文件并进行托管调试
  3. 查看并行堆栈,发现大部分线程均处于MySql.Data.MySqlClient.MySqlPoolManager.GetPool这个函数的调用中。并在此处进入了本机代码。处于其他调用堆栈的线程屈指可数。

代码分析

  1. 由于Mysql.Data.dll没有对应的pdb文件(Oracle没有提供),所以在Visual Studio中不能进入其中的代码,因此直接反编译,找到该函数,代码如下:

函数中,第一句的GetKey函数如下,其中有一个lock。其中代码仅仅是赋值,或是在集成认证的情况下才执行。所以卡住的可能性不大。

第二句是个赋值,且MysqlPoolManager.pools是个字段(field),理论上不会卡住。

第二个lock中,如果指定key对应的缓存已存在,则lock会很快返回。如果不存在,则执行new MysqlPool(setttings);函数代码如下:

其主要功能有

  1. 创建一个事件,用于获取连接时的异步等待
  2. 根据settings持久化设置
  3. 初始化池驱动列表、队列
  4. 按照配置的minSize创建指定数量的连接。
  5. 创建一个过程缓存,代码如下

这5个步骤中,最可能耗时较久的是步骤d。其他步骤理论上不会有问题。

步骤d中的代码,虽然就一个函数,但是代码很多。

经过不停的查看代码,发现其主要功能是根据连接字符串中的设置,创建一个指定类型的连接。其底层创建代码如下:

可以看到,任何创建Stream失败的情况都会抛出异常,最终导致连接池创建失败。

其中第一句,GetStream的底层代码如下:

开始连接(BeginConnect)后,即开始了等待。等待的超时默认值如下:

2147483s,即596h。如果有连接到数据库服务器的网络有问题或其他原因导致连接不成功,而也未触发其他导致失败的情况,则会一直等下去。如果推断正确,那么所有线程中,一定有线程的调用堆栈在如下位置:

对Dump文件中的所有线程堆栈排序,有且仅有一个线程处于该调用堆栈处。高亮行正是上述堆栈的函数名CreateSocketStream上面一行就是WaiteOne。之后进入本机代码。

那么根本原因也就清楚了:一个连接的创建卡住了数据库连接创建,间接卡住了连接池的锁,又间接卡住了其他连接池的使用和创建。导致所有数据库连接不可用。所以,所有进入的请求经过运行,全部堆在GetPool这里。

解决方法:

  1. 保证网络正常(跨机房专线稳定性不可控,有人摇晃光纤玩 o(∩_∩)o 或者其他原因导致流量堵塞)
  2. 容易卡的数据库连接分离出去到单独的进程。这样由于不共享锁,所以不会卡住其他线程池的使用和创建。
  3. 需要跨机房的业务,在数据所在机房单独提供api,内网失效时可以走外网。
  4. 容易卡住的线程池连接字符串中设置minPoolSize=0。这样创建连接池时,不预创建连接而影响其他连接池。但是,对于突发流量增长的情况,响应可能不够及时。
  5. 设置一个合理的ConnectionTimeout。可以有效避免连接创建时卡住,导致api无响应和其他副作用。

其他在源代码中发现的需要注意的地方

  1. 连接池中空闲连接的空闲时间是180s。
  2. 清理周期第一次是188s,之后保持180s。
  3. 如果连接池中的空闲连接数大于设置的minPoolSize,则清理空闲连接直到minPoolSize。
  4. ConnectionTimeout用于几个地方
    1. ) 连接socket时的等待超时
    2. ) 连接之后,连接上的读写超时。
    3. ) 从已空且总数达上限的连接池中,等待可用连接时的等待超时

以上所有信息基于.Net版本Mysql.Data 6.9.9版本反编译分析。

一次Mysql连接池卡死导致服务无响应问题分析(.Net Mysql.Data 6.9.9)的更多相关文章

  1. tomcat服务无响应堆栈分析

    tomcat服务突然无响应了,导出内存堆栈和线程堆栈,分析后发现是同步锁使用不合理导致的. [root@prd-dtb-web-01 ~]# [root@prd-dtb-web-01 ~]# jmap ...

  2. ArcGIS Server浏览地图服务无响应原因分析说明

    1.问题描述 从4月17号下午5时起,至18号晚9点,客户单位部分通过ArcGIS Server发布的地图服务(该部分地图服务的数据源为数据库SJZX)无法加载浏览,表现为长时间无响应.同时,通过Ar ...

  3. mysql连接池模块

    如果不想程序在查询数据时卡死或等待过长时间,一般不推荐在node中开启一个连接后全部查询都用这个链接并且不关闭.因为node里面的mysql不像php里的那样会在完成查询后断开,只要不主动断开,连接一 ...

  4. 连接池设置导致的“血案” 原创: 一页破书 一页破书 5月6日 这个问题被投诉的几个月了,一直没重视——内部客户嘛😿 问题现象: 隔几周就会出现 A服务调用B服务超时 脚趾头想就是防火墙的问题,A、B两服务之间有防火墙 找运维查看防火墙日志确实断掉了tcp连接,但是是因为B服务5分钟没有回包,下面这个表情就是我当时的心情——其实我们在防火墙、A服务、B服务都抓包了,几十个G的t

    连接池设置导致的“血案” 原创: 一页破书 一页破书 5月6日 这个问题被投诉的几个月了,一直没重视——内部客户嘛

  5. Java Mysql连接池配置和案例分析--超时异常和处理

    前言: 最近在开发服务的时候, 发现服务只要一段时间不用, 下次首次访问总是失败. 该问题影响虽不大, 但终究影响用户体验. 观察日志后发现, mysql连接因长时间空闲而被关闭, 使用时没有死链检测 ...

  6. .Net中如何使用MySql连接池

    提供一份官方的译文.翻译也挺辛苦的!! 6.4 Using Connector/Net with Connection Pooling 6.4在Connector/Net中使用连接池 The Conn ...

  7. workerman如何写mysql连接池

    首先要了解为什么用连接池,连接池能为你解决什么问题 连接池主要的作用1.减少与数据服务器建立TCP连接三次握手及连接关闭四次挥手的开销,从而降低客户端和mysql服务端的负载,缩短请求响应时间2.减少 ...

  8. 解决Mysql连接池被关闭 ,hibernate尝试连接不能连接的问题。 (默认mysql连接池可以访问的时间为8小时,如果超过8小时没有连接,mysql会自动关闭连接池。系统发布第二天访问链接关闭问题。

    解决Mysql连接池被关闭  ,hibernate尝试连接不能连接的问题. (默认MySQL连接池可以访问的时间为8小时,如果超过8小时没有连接,mysql会自动关闭连接池. 所以系统发布第二天访问会 ...

  9. nodejs + redis/mysql 连接池问题

    nodejs + redis/mysql 连接池问题 需不需要连接池 连接池的作用主要是较少每次临时建立连接所带来的开销.初步一看,nodejs运行单线程上,它不能同时使用多个连接,乍一看是不需要连接 ...

随机推荐

  1. Mysql uploader File

    前几天和哥们做一次渗透测试,内网情况.防护相当严格. 内网不允许访问DMZ,DMZ不允许访问内网,除了服务端口,比如80,3306. 经过长时间的分析,就发现本机连接了内网的一个MYQL,发现WEB开 ...

  2. 面试笔试总结(一)之 C++基础

    C++ 1.智能指针 内存管理 垃圾回收 指针问题 资源管理(内存就是资源) 可以通过引用计数的机制...实现内存回收,不要让内存泄漏. 涉及到内存的泄露的问题: 当创建一个对象的时候(new)而在对 ...

  3. hiho#1080 更为复杂的买卖房屋姿势 线段树+区间更新

    #1080 : 更为复杂的买卖房屋姿势 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho都是游戏迷,“模拟都市”是他们非常喜欢的一个游戏,在这个游戏里面他们 ...

  4. linux 用 grep 查找单个或多个字符串(关键字)

    1.单个 cat /tmp/php.log | grep "成功" 所有的成功都会被查询出来. 2.多个,并列查询 cat /tmp/php.log | grep "推荐 ...

  5. angularjs定时任务的设置与清除

    人们似乎常常将AngularJS中 的$timeOut()  $interval()函数看做是一个内置的.无须在意的函数.但是,如果你忘记了$timeOut()$interval()的回调函数将会造成 ...

  6. NOIP2018小反思

    今天下午做了一道叫邮票 Stamps的题.敲代码的时候就发现,好像和去年D1T2货币系统有点像,原理都是一个完全背包DP.做完之后交上去发现有几个点RE了,于是马上把数组改大,AC. 我赶忙找到去年那 ...

  7. 重新学习MySQL数据库10:MySQL里的那些日志们

    重新学习MySQL数据库10:MySQL里的那些日志们 同大多数关系型数据库一样,日志文件是MySQL数据库的重要组成部分.MySQL有几种不同的日志文件,通常包括错误日志文件,二进制日志,通用日志, ...

  8. 在Intellij Idea中使用Maven创建Spring&SpringMVC项目

    环境及版本 Jetbrains Intellij Idea 15.0.6 Spring 4.1.6 JDK 1.8.0_20 Tomcat 8 Windows 10 从 Maven archetype ...

  9. nyoj998——欧拉+折半查找

    Sum 时间限制:1000 ms  |  内存限制:65535 KB 难度:3   描述 给你一个数N,使得在1~N之间能够找到x使得x满足gcd( x ,  N  ) >= M, 求解gcd( ...

  10. ssh原理与应用

    一.什么是SSH? 简单说,SSH是一种网络协议,用于计算机之间的加密登录. 如果一个用户从本地计算机,使用SSH协议登录另一台远程计算机,我们就可以认为,这种登录是安全的,即使被中途截获,密码也不会 ...