MySQL Too Many Connections

一、前言

上一篇 《磁盘爆了》  我们讲磁盘撑爆造成Java应用无法启动,今天我们来讲一下MySQL连接被撑爆应用启动后连不上数据库的问题。

二、max_connections配置

我们自己安装的开源MySQL5.6 默认的max_connections(最大连接数)值为151,为什么是151咱也搞不清楚,以前版本好像是100,阿里云或亚马逊RDS max_connections是根据你购买不同型号机器而不同,从600到几万都有,自己安装的MySQL最大连接数配置其实可以参考阿里云的配置,如下图:

MySQL Too Many Connections_第1张图片

在MySQL中查看max_connections设置的值,使用命令show variables like "max_connections";

  • 临时设置:调整max_connections的值,在MySQL命令行中执行后可以立即生效,但MySQL服务器重启后会被恢复成默认的设置。

    set global max_connections=1000;

  • 永久设置:在/etc/my.cnf 的[mysqld]下面添加设置代码,然后重启就可以了

那是否这里想设置多少都可以呢,这肯定也是不行的,一方面与机器CPU、内存有关,另一方面与LInux、MySQL文件句柄数都有关系。

三、Linux文件句柄数

Linux文件句柄数限制分为内核句柄数限制与用户句柄数限制。

  • 内核句柄数

    查看内核句柄数限制  cat /proc/sys/fs/file-max,不同机器这个值不一样。

    修改内核句柄数限制  vi /etc/sysctl.conf  fs.file-max=655350,修改后需要重启系统。

  • 用户句柄数

    查看用户句柄数限制  ulimit -n  ,它规定了单个进程可以打开最大文件句柄数,Socket连接数也算在内

    修改用户句柄数限制:vi /etc/security/limits.conf

        * soft nofile 65535

           * hard nofile 65535   修改后同样需要重新系统。

查看某个进程最大句柄数限制和当前打开的句柄数,下图是我一台测试机查看的数据。

MySQL Too Many Connections_第2张图片

四、MySQL的open_files_limit

命令 show variables  like 'open_files_limit';可以查看当前MySQL允许打开的文件句柄数,我们在设置max_connections最大连接数时不能超过 open_files_limit的值,因为 open_files_limit除了包含Socket连接还包含打开的文件数(数据库表文件等,如下图),如果max_connections大于open_files_limit MySQL是无法启动的。

MySQL Too Many Connections_第3张图片

设置MySQL最大句柄数

vim /usr/lib/systemd/system/mysqld.service 

加入LimitNOFILE=1024,即可设置open_files_limit的大小。

五、一个小实验

将max_connectrions的值设置为【2】个,重启MySQL,然后写一个Python脚本启动10个线程连接数据库查询数据,目的就是为了撑爆连接数,代码如下,注:本来想用Go的协程写这段代码,但Go连接数据库还没有玩过,短时间内写不出来,就用Python搞搞了。

MySQL Too Many Connections_第4张图片

然后用show processlist查看数据可以看到有【3】连接,其中有一个连接是预留给超级用户连接使用。

Python脚本执行后,除了两个线程查询返回数据,其它线程都报

pymysql.err.OperationalError: (1040, 'ny connections')错误,1040错误即连接数超过了MySQL设置的最大连接数。

六、上次测试环境产生 Too Many Connections原因

1、测试环境MySQL是自己搭建的,默认max_connections为151

2、测试环境Java应用都是使用连接池,每个应用启动后就会创建几十个连接,我们有多个应用启动,然后开发人员开发机启动调试,加起来连接数很容易就超过了151的值,设置一下/etc/my.conf中max_connections即可解决。

3、突然想起来以前和php程序员聊天的时候,说php不需要连接池,因为php一个请求对应一个进程,请示结束进程也结束,它不存在多线程竟争的问题,所以可以用一个常驻进程对应一个数据库连接来避免重复连接造成的开销(php没玩过不太了解,不确定对不对),而Java是单进程多线程架构,依赖于数据库连接池来减少频繁建立连接的开销。

你可能感兴趣的:(存储,mysql,数据库)