Can not connect to MySQL server. Too many connections”-mysql
实际工作场景中我们应该都会遇到类似的故障,一般都是处理表面参数解决,今天整理一下自己对这个报错的认识吧,通过以下三点了解以下~
- 首先了解数据库基础的参数,查看数据库状态。
- 遇到这种错误如何快速恢复
- 业务层面如何优化
- 拓展关于连接不上数据库情况
一、了解数据库基础的参数
1.查看当前连接数
show PROCESSLIST
与 show full PROCESSLIST
(查看当前数据库所有连接,包含空闲连接与活跃连接)
show PROCESSLIST
最多展示100条连接,show full PROCESSLIST
可展示全部
mysql> show full processlist;
+-----+-------+-------------------+------+---------+------+-------+-----------------------+
| Id | User | Host | db | Command | Time | State | Info |
+-----+-------+-------------------+------+---------+------+-------+-----------------------+
| 174 | hotel | redis.local:46846 | NULL | Query | 0 | NULL | show full processlist |
+-----+-------+-------------------+------+---------+------+-------+-----------------------+
1 row in set (0.00 sec)
mysql>
如发现大量sleep连接,说明空闲连接数过多,不多的话也不需要处理,如果涉及到很多下面会介绍如何处理
2.查看最大连接数
系统默认安装系统最大连接数为100,可以手动调整,用sql命令为临时调整,如要永久调整请修改mysql配置文件。
mysql> show variables like '%max_connections%';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 151 |
+-----------------+-------+
1 row in set (0.01 sec)
mysql>
如何调整连接数设置?
mysql> set GLOBAL max_connections = 200;
Query OK, 0 rows affected (0.00 sec)
mysql> show variables like '%max_connections%';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 200 |
+-----------------+-------+
1 row in set (0.00 sec)
mysql>
3.查看数据库当前状态
如下,能看到数据库状态信息(只截取部分),可以看到Max_used_connections
同时使用的连接数的最大数目
mysql> show status;
+-----------------------------------+--------------+
| Variable_name | Value |
+-----------------------------------+--------------+
| Aborted_clients | 107 |
| Aborted_connects | 50 |
| Binlog_cache_disk_use | 0 |
| Binlog_cache_use | 0 |
| Bytes_received | 241 |
| Bytes_sent | 492 |
| Max_used_connections | 20 |
| Open_files | 118 |
| Open_streams | 0 |
| Open_table_definitions | 256 |
| Open_tables | 64 |
| Opened_files | 13538 |
二、遇到这种错误如何快速恢复
1.简单直接,先修改参数让业务恢复,随后自己改配置或者联系所在云服务厂商修改,
2.如果都是正常连接那说明业务需要拓展了,如果非正常活跃连接那么可以深入查一下业务情况了,需要做业务优化。
mysql> set GLOBAL max_connections = 1000;
Query OK, 0 rows affected (0.00 sec)
mysql> show variables like '%max_connections%';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 1000 |
+-----------------+-------+
1 row in set (0.00 sec)
三、业务层面的优化
具体实例也许就是自己业务当下存在的问题,可我的数据库配置比较高所以没爆发此类问题。
以PHP程序为例子,以下是非高峰期数据库连接情况如图:
可以看到总连接数多大多数都是空闲连接,为什么空闲连接没有释放呢?
- 原因,来自阿里帮助文档
应用使用长连接模式:对于长连接模式(比如Java应用),应用侧应该配置连接池。连接池的初始连接数设置过高,应用启动后建立多个到RDS实例空闲连接。
应用使用短连接模式:对于短连接模式(比如PHP应用),出现大量的空闲连接说明应用没有在查询执行完毕后显式的关闭连接。 - 解决方法
通过DMS或者kill
命令来终止当前空闲会话,利用show processlist
查看id,然后kill id
即可
修改应用,长连接模式需要启用连接池的复用功能(建议也启用连接检测功能)。
修改应用,短连接模式需要在代码中修改查询结束后调用关闭连接的方法。
对于非交互模式连接,在控制台的参数设置里设置wait_timeout参数为较小值。wait_timeout
参数控制非交互模式连接的超时时间(单位秒,默认值为24小时即86400秒),当非交互式连接空闲时间超过wait_timeout
指定的时间后,RDS实例会主动关闭连接。
拓展:
在MySQL实例连接数完全打满的情况下,通过DMS或者其他方式是无法连接实例的;因此对于长连接模式,建议连接池的最大连接数要略小于实例规格的连接数限制,比如保留10个连接给DMS或其他管理操作使用。当发生无法连接的情况时,建议先在控制台修改wait_timeout参数为较小值,促使RDS实例主动关闭空闲时间超过阈值的连接。
通常情况下,应用到RDS实例会采用非交互模式,具体采用哪个模式需要查看应用的连接方式配置,比如PHP通过传递MYSQL_CLIENT_INTERACTIVE常量给mysql_connect()函数即可开启连接的交互模式。
wait_timeout和interactive_timeout这两个参数的修改,修改前已经存在的会话保持修改前的设置,修改后新创建的会话使用新的参数设置。