38 案例实战:数据库无法连接故障的定位,Too many connections
今天要给大家分析另外一个真实的大家都经常会碰到的数据库生产故障,就是数据库无法连接的问题。
大家会看到的异常信息往往是 ERROR 1040(HY000): Too many connections
,这个时候就是说数据库的连接池里已经有太多的连接了,不能再跟你建立新的连接了!
数据库自己其实是有一个连接池的,你的每个系统部署在一台机器上的时候,你那台机器上部署的系统实例/服务实例自己也是有一个连接池的,你的系统每个连接Socket都会对应着数据库连接池里的一个连接Socket,这就是TCP网络连接,如下图所示。

所以当数据库告诉你Too many connections
的时候,就是说他的连接池的连接已经满了,你业务系统不能跟他建立更多的连接了!
曾经在我们的一个生产案例中,数据库部署在64GB的大内存物理机上,机器配置各方面都很高,然后连接这台物理机的Java系统部署在2台机器上,Java系统设置的连接池的最大大小是200,也就是说每台机器上部署的Java系统,最多跟MySQL数据库建立200个连接,一共最多建立400个连接,我们看下图示意。

但是这个时候如果MySQL报异常说Too many Connections
,就说明目前MySQL甚至都无法建立400个网络连接?这也太少了吧!毕竟是高配置的数据库机器!
于是我们检查了一下MySQL的配置文件,my.cnf
,里面有一个关键的参数是max_connections
,就是MySQL能建立的最大连接数,设置的是800。
那奇怪了,明明设置了MySQL最多可以建立800个连接,为什么居然两台机器要建立400个连接都不行呢?
这个时候我们可以用命令行或者一些管理工具登录到MySQL去,可以执行下面的命令看一下:
show variables like 'max_connections'
此时你可以看到,当前MySQL仅仅只是建立了214个连接而已!
所以我们此时就可以想到,是不是MySQL根本不管我们设置的那个max_connections
,就是直接强行把最大连接数设置为214了?于是我们可以去检查一下MySQL的启动日志,可以看到如下的字样:
Could not increase number of max_open_files to more than mysqld (request: 65535)
Changed limits: max_connections: 214 (requested 2000)
Changed limits: table_open_cache: 400 (requested 4096)
所以说,看看日志就很清楚了,MySQL发现自己无法设置max_connections
为我们期望的800,只能强行限制为214了!
这是为什么呢?简单来说,就是因为底层的linux操作系统把进程可以打开的文件句柄数限制为了1024了,导致MySQL最大连接数是214!
如下图所示。
