2

线上MySQL不可用,报错数据库无法连接

 2 years ago
source link: https://www.51cto.com/article/700884.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
线上MySQL不可用,报错数据库无法连接-51CTO.COM
线上MySQL不可用,报错数据库无法连接
作者:JavaEdge 2022-02-09 11:22:22
数据库自己有个连接池,你的每个系统部署在机器时,那台机器上部署的系统实例/服务实例自己也有个连接池,你的系统每个连接Socket都对应DB连接池里的一个Socket连接,这就是TCP连接。

ERROR 1040(HY000): Too many connections:DB连接池里已有太多连接,不能再和你建立新连接。

数据库自己有个连接池,你的每个系统部署在机器时,那台机器上部署的系统实例/服务实例自己也有个连接池,你的系统每个连接Socket都对应DB连接池里的一个Socket连接,这就是TCP连接:

f3f46af84f23cd4c369038c37c376bc572c3ad.png

当MySQL告诉你Too many connections,就是在传达它的连接池的连接已经满了,你这业务系统不能再和它建立新的连接。

DB部署在64G内存大机器,而连接这台物理机的Java业务系统部署在2台机器,Java系统的连接池最大大小为200,即每个Java业务系统节点,最多和MySQL建立200个连接,共最多建立400个连接。

但这时若MySQL报异常Too many Connections,说明目前MySQL无法建立400个网络连接。这也太少了吧,这可是高配置机器!

于是检查了my.cnf,有个关键参数是max_connections,即MySQL能建立的最大连接数,设置的800。那为啥两台机器就只需建立400个连接都不行?

登录到MySQL机器,执行如下命令:

show variables like 'max_connections'

​​可观察到,当前MySQL仅建立了214个连接而已!难道MySQL根本不在乎我们设置的这参数?

检查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!

Linux文件句柄数量被限制也会导致MySQL最大连接数被限制。

核心就如下命令:

ulimit -HSn 65535

然后就能用如下命令,检查最大文件句柄数是否被修改:

cat /etc/security/limits.conf cat /etc/rc.local

若都修改好之后,可在MySQL的my.cnf里确保max_connections参数也调整好了,然后重启服务器、重启MySQL,这样linux的最大文件句柄就会生效,MySQL最大连接数也会生效了。

此时再尝试业务系统去连接DB,就没问题了。

为何Linux最大文件句柄限制为1024时,MySQL最大连接数是214?MySQL源码中就是有个计算公式,算下来就是这样的结果。

linux默认会限制你每个进程对机器资源的使用,包括:

  • 可打开的文件句柄的限制
  • 可打开的子进程数的限制
  • 网络缓存的限制
  • 最大可锁定的内存大小

因为linux os设计的初衷,就是要尽量避免你某个进程一下子耗尽机器上的所有资源,所以他默认都是会做限制的。

对我们来说,常见问题就是文件句柄的限制。

因为若linux限制你一个进程的文件句柄太少,就会导致我们无法创建大量网络连接,我们的系统进程就无法正常工作。比如MySQL运行时,其实就是Linux上的一个进程,那么他其实是需要跟很多业务系统建立大量的连接的,结果你限制了他的最大文件句柄数量,那么他就不能建立太多连接了!

所以,你在生产环境部署了个系统,比如DB系统、MQ系统、存储系统、Cache系统后,都需要调整Linux的一些内核参数,这个文件句柄数量一定要调整,通常得设为65535。

比如Kafka之类的MQ,在生产环境部署时,若不优化linux内核参数,会导致Kafka可能无法创建足够的线程,此时也无法运行。

所以可用ulimit命令设置每个进程被限制使用的资源量,用

# 进程被限制使用的各种资源的量
ulimit -a

b57857801f0bac086a2241c492bc646658d47c.png

  • core file size 进程崩溃时的转储文件的大小限制
  • max locked memory 最大锁定内存大小
  • open files 最大可以打开的文件句柄数量
  • max user processes就是最多前可进以拥有的子进程数量。久性的设置进程的资源

设置之后,要确保变更落地到/etc/security/limits.conf文件,永打印限制

所以执行ulimit -HSn 65535命令后,要用如下命令检查一下是否落地到配置文件里去了。

cat /etc/security/limits.conf

cat /etc/rc.local

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK