章
目
录
在MySQL运维的过程中,大家或多或少都遇到过一些问题吧?今天咱们就来聊聊其中一个常见的报错——“Too many connections”,看看怎么巧妙地解决它。
一、报错原因及处理难点
在日常的MySQL运维工作里,参数设置不合理是常有的事,这也导致MySQL在运行时状况频发。“Too many connections”这个报错,简单来说,就是并发量太大,超过了MySQL设置的最大连接数,所有连接都被占用了,新的连接请求就没办法处理,只能报错。报错信息一般是这样:
ERROR 1040 (HY000): Too many connections
遇到这个报错,很多人第一反应可能是去修改最大连接数max_connections
的值。但这里面有个麻烦事儿,当出现“Too many connections”报错时,用mysql客户端连接进行动态修改是行不通的。要是修改配置参数后重启MySQL服务,确实能让max_connections
的值生效,可生产环境里业务正在运行,哪能随便重启呀,这会影响业务正常访问的。那有没有不重启就能解决问题的办法呢?还真有!
二、借助GDB工具
这个神奇的工具就是GDB。大家可能对GDB比较熟悉的是它作为调试工具的功能,不过今天咱们要用的是它在线修改配置参数的能力。接下来,通过一个实验场景,看看怎么用GDB解决“Too many connections”的问题。
(一)准备实验环境
首先,准备一个MySQL 5.7.40版本的数据库实例。然后创建一个空库,命令如下:
mysql> create database jiangshifeng;
Query OK, 1 row affected (0.00 sec)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| jiangshifeng |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
mysql> use jiangshifeng;
Database changed
mysql> show tables;
Empty set (0.00 sec)
接着,把这个实例的最大连接数设置为10,操作如下:
mysql> set global max_connections=10;
Query OK, 0 rows affected (0.01 sec)
mysql> show variables like '%max_conn%';
+--------------------+-------+
| Variable_name | Value |
+--------------------+-------+
| max_connect_errors | 100 |
| max_connections | 10 |
+--------------------+-------+
2 rows in set (0.00 sec)
(二)安装并验证GDB工具
安装GDB工具也很简单,执行下面这条命令就行:
yum install -y gdb
安装完成后,可以验证一下是否安装成功:
[root@node1 ~]# gdb
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>
(gdb)
(gdb) q
[root@node1 ~]#
(三)模拟报错场景
现在,用sysbench进行压测,模拟在“jiangshifeng”这个空库里创建11张表,每张表的数据量为20000000条,连接线程数设为15,命令如下:
sysbench /usr/share/sysbench/oltp_common.lua --mysql-host=127.0.0.1 --mysql-port=3306 --mysql-user=root --mysql-password=123456 --mysql-db=jiangshifeng --db-driver=mysql --tables=11 --table-size=20000000 --report-interval=15 --threads=15 prepare
压测之后,再用客户端工具连接mysql,就会出现“Too many connections”报错:
[root@node1 ~]# mysql -uroot -p123456
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1040 (HY000): Too many connections
[root@node1 ~]#
(四)使用GDB修改参数
下面就是关键步骤啦,用GDB工具来设置max_connections
参数。这里有两种方法:
- 方法一:
gdb -p $(pidof mysqld) -ex "set max_connections=50" -batch
这条命令的意思是,通过pidof mysqld
获取MySQL服务进程ID,然后用GDB工具针对这个进程,把max_connections
的值设置为50 ,-batch
参数表示执行完命令后自动退出。
- 方法二:
[root@node1 ~]# ps -ef | grep mysql
root 1320 1 0 Mar17 ? 00:00:00 /bin/sh /usr/local/mysql/bin/mysqld_safe --datadir=/DB/mysql --pid-file=/DB/mysql/node1.pid
mysql 1582 1320 9 Mar17 ? 03:33:44 /usr/local/mysql/bin/mysqld --basedir=/usr/local/mysql --datadir=/DB/mysql --plugin-dir=/usr/local/mysql/lib/plugin --user=mysql --log-error=node1.err --pid-file=/DB/mysql/node1.pid --socket=/tmp/mysql.sock --port=3306
[root@node1 ~]# gdb -p 1582
...
(gdb) p max_connections
$1 = 10
(gdb)
(gdb) set max_connections=50
(gdb) p max_connections
$4 = 50
(gdb)
$5 = 50
(gdb) q
A debugging session is active.
Inferior 1 [process 1582] will be detached.
Quit anyway? (y or n) y
Detaching from program: /usr/local/mysql/bin/mysqld, process 1582
[Inferior 1 (process 1582) detached]
[root@node1 sysbench]#
这种方法是先通过ps -ef | grep mysql
命令找到MySQL服务的进程ID(这里是1582),然后用GDB工具连接这个进程。先是查看当前max_connections
的值(显示为10),接着设置为50 ,再查看确认修改成功,最后退出GDB。
(五)验证修改结果
修改完之后,再次登录mysql验证一下:
[root@node1 ~]# mysql -uroot -p123456
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 146
Server version: 5.7.40-log MySQL Community Server (GPL)
Copyright (c) 2000, 2022, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
mysql> show variables like '%max_conn%';
+--------------------+-------+
| Variable_name | Value |
+--------------------+-------+
| max_connect_errors | 100 |
| max_connections | 50 |
+--------------------+-------+
2 rows in set (0.10 sec)
从结果可以看到,MySQL的最大连接数max_connections
已经成功修改为50,而且之前sysbench压测的数据还在正常运行,基本没有影响业务。
三、总结与建议
通过上面的实验,我们成功用GDB工具在不重启MySQL的情况下,修改了max_connections
参数。其实,用同样的方式,也可以修改其他MySQL参数。
不过要提醒大家,虽然这次实验成功了,但用这种方式修改参数还是有一定风险的。我们不能因为有了这个工具就掉以轻心。在日常工作中,一定要严格遵守开发规范。就拿最大连接数来说,我们要提前评估好业务最大并发峰值,把最大连接数设置得比峰值大一些,这样能尽量避免连接数被打满的情况。但也不是设置得越大越好,还得考虑物理资源,最好配合压测,找到一个合适的值。不然程序出现异常死锁,不断申请新连接,导致连接数异常打满,可能会直接让数据库崩溃。
希望今天分享的内容能帮到大家,要是在处理这类问题时有什么心得,欢迎一起交流!