文章目录
1. 文章引言
我们在工作的过程中,经常会遇到的Too many connections
的错误。
也许,这个错误是在Java
代码中出现的,如下代码所示:
java.sql.SQLNonTransientConnectionException: Data source rejected establishment of connection, message from server: "Too many connections"
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:110)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:833)
at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:453)
at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:246)
at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:198)
at com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1643)
at com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1709)
at com.alibaba.druid.pool.DruidDataSource$CreateConnectionThread.run(DruidDataSource.java:2813)
又或许,这个错误是由MySQL
报出的,如下图所示:
又或者,这个错误由其他语言报出,比如golang、Python,PHP
等等。
但不论是哪种语言报出的这个错误,我们都需要了解MySQL
的连接数机制,包括如下才能准确无误地解决这个错误,即Too many connections
。
接下来,我便从连接总数、连接活跃数、最大并发数
详细说明MySQL
的连接数。
2. MySQL连接数
2.1 连接总数
我们可以执行如下命令,来查看MySQL
的连接总数:
mysql> show status like 'Threads%';
+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| Threads_cached | 4 |
| Threads_connected | 6 |
| Threads_created | 264 |
| Threads_running | 1 |
+-------------------+-------+
4 rows in set (0.00 sec)
当然,我们也可以使用如下代码,查看全局的连接数量:
mysql> show global status like 'Threads%';
+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| Threads_cached | 10 |
| Threads_connected | 16 |
| Threads_created | 286 |
| Threads_running | 2 |
+-------------------+-------+
4 rows in set (0.00 sec)
MySQL
的连接总数主要看Threads_connected
的值,这个表示打开的连接数,也就是连接总数。
Threads_connected
跟show processlist
结果相同,表示当前连接总数,如下代码所示:
mysql> show processlist;
+-----+------+-----------------+---------+---------+------+----------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+-----+------+-----------------+---------+---------+------+----------+------------------+
| 588 | root | localhost:52547 | test | Sleep | 6715 | | NULL |
| 589 | root | localhost:52548 | test | Sleep | 6715 | | NULL |
| 590 | root | localhost:52549 | test | Sleep | 6715 | | NULL |
| 591 | root | localhost:52550 | test | Sleep | 6715 | | NULL |
| 592 | root | localhost:52551 | test | Sleep | 6711 | | NULL |
| 594 | root | localhost:55797 | NULL | Query | 0 | starting | show processlist |
+-----+------+-----------------+---------+---------+------+----------+------------------+
6 rows in set (0.00 sec)
Threads_connected
的值为6,而show processlist
查出6条数据。
因而,Threads_connected
跟show processlist
结果相同。
2.2 活跃数
活跃数可以看上述查询结果中的Threads_running
的值。
Threads_running
数值指的是激活的连接数,这个数值一般远低于Threads_connected
数值。
准确的来说,Threads_running
是代表当前并发数,上述当前并发数为1。
另外Threads_cached
和Threads_created
分别表示:
-
Threads_cached
:MySQL
管理的线程池中还有多少可以被复用的资源。 -
Threads_created
:表示创建过的线程数。
如果发现Threads_created
值过大的话,表明MySQL
服务器一直在创建线程,这也是比较耗资源。可以适当增加配置文件中的thread_cache_size
值,如下代码所示:
mysql> set global thread_cache_size=60;
Query OK, 0 rows affected (0.00 sec)
2.3 最大并发数
查询数据库当前设置的最大连接数,如下代码所示:
mysql> show variables like 'max_connections';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 151 |
+-----------------+-------+
1 row in set, 1 warning (0.04 sec)
MySQL
默认最大连接数max_connections
为151
,其实MySQL
还给root
留了多一个通道,真正的最大连接数为max_connections + 1
。
但实际工作中因为各种原因,这个1
也有可能被占用。
这时,我们无法通过登录MySQL
调整参数的方法来处理这个错误。
当然,我们可按如下命令修改最大连接数:
mysql> set GLOBAL max_connections=1000;
Query OK, 0 rows affected (0.04 sec)
重新查询最大连接数,来校验是否设置成功:
mysql> show variables like 'max_connections';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 1000 |
+-----------------+-------+
1 row in set, 1 warning (0.01 sec)
但是,这只是临时修改,重启mysql
会失效。
因而,需要修改mysql
的配置/etc/my.cnf
,如下图所示:
修改完毕后,重启mysql5.7
即可:
3. 重要补充
3.1 show status和show global status区别
-
show status
:本次会话的参数状态 -
show global status
:本次MYSQL
服务到现在总请求数,即systemctl start mariadb
到现在的总请求,可以使用systemctl restart mariadb
重置该数值。
3.2 show status like ‘%变量名%’
变量名如下:
-
Aborted_clients
:由于客户没有正确关闭连接已经死掉,已经放弃的连接数量。 -
Aborted_connects
:尝试已经失败的MySQL
服务器的连接的次数。 -
Connections
:试图连接MySQL
服务器的次数。 -
Created_tmp_tables
:当执行语句时,已经被创造了的隐含临时表的数量。 -
Delayed_insert_threads
:正在使用的延迟插入处理器线程的数量。 -
Delayed_writes
:用INSERT DELAYED
写入的行数。 -
Delayed_errors
:用INSERT DELAYED
写入的发生某些错误(可能重复键值)的行数。 -
Flush_commands
:执行FLUSH
命令的次数。 -
Handler_delete
:请求从一张表中删除行的次数。 -
Handler_read_first
:请求读入表中第一行的次数。 -
Handler_read_key
:请求数字基于键读行。 -
Handler_read_next
:请求读入基于一个键的一行的次数。 -
Handler_read_rnd
:请求读入基于一个固定位置的一行的次数。 -
Handler_update
:请求更新表中一行的次数。 -
Handler_write
:请求向表中插入一行的次数。 -
Key_blocks_used
:用于关键字缓存的块的数量。 -
Key_read_requests
:请求从缓存读入一个键值的次数。 -
Key_reads
:从磁盘物理读入一个键值的次数。 -
Key_write_requests
:请求将一个关键字块写入缓存次数。 -
Key_writes
:将一个键值块物理写入磁盘的次数。 -
Max_used_connections
:同时使用的连接的最大数目。 -
Not_flushed_key_blocks
:在键缓存中已经改变但是还没被清空到磁盘上的键块。 -
Not_flushed_delayed_rows
:在INSERT DELAY
队列中等待写入的行的数量。 -
Open_tables
:打开表的数量。 -
Open_files
:打开文件的数量。 -
Open_streams
打开流的数量(主要用于日志记载) -
Opened_tables
已经打开的表的数量。 -
Questions
发往服务器的查询的数量。 -
Slow_queries
要花超过long_query_time时间的查询数量。 -
Threads_connected
当前打开的连接的数量。 -
Threads_running
不在睡眠的线程数量。 -
Uptime
服务器工作了多长时间,单位秒。
3.3 show variables like ‘xxx’
show variables like xxx
常见的查询,可以参考这篇博文:全网详细介绍MySQL中的show variables like xxx 详解