1. 背景
在日常的 MySQL 運維中,難免會出現參數設置不合理,導致 MySQL 在使用過程中出現各種各樣的問題。
今天,我們就來講解一下 MySQL 運維中一種常見的問題:最大連接數設置不合理,一旦到了業務高峰期就會出現連接數打滿的問題。
報錯信息
ERROR 1040 (HY000): Too many connections
報錯原因
這個問題,無非就是并發過高,導致最大連接數被用完引起的。
解決辦法
重新設置最大連接數 max_connections
的值。
處理痛點
- 出現了
Too many connections
的報錯信息,無法用 mysql 客戶端連接進行動態修改。 - 修改配置參數后重啟,確實可以讓
max_connections
的值重新生效,但是生產環境有業務訪問,肯定是不能隨便重啟的。
2. GDB 工具
基于以上種種問題和主要痛點,那么我們就來試試 gdb 工具吧,讓我們在不重啟的狀態下,照樣可以修改 MySQL 的參數 !!!
gdb 工具的介紹在這里就不做過多贅述了,其實大多數場景下,都是把它當做調試工具來用。今天我們更多的是用到 gdb 在線修改配置參數的功能。
3. 處理過程
下面,我們就通過一個實驗場景,來模擬 mysql
連接數打滿,出現 Too many connections
的問題,通過 gdb 工具的解決步驟。
- 準備一個數據庫實例,數據庫版本為 MySQL 5.7.40。
- 創建一個空庫
jiangshifeng
。
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 工具。
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 工具設置
max_connections
參數。
方法一
gdb -p $(pidof mysqld) -ex "set 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]#
- 再次登錄驗證。
[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
已經成功修改。并且,前面的 sysbench 壓測數據還正常運行,可以理解為基本上不影響業務。
4. 總結
- 本次雖然只介紹了通過不重啟的方式,用 gdb 修改
max_connections
參數。但是其他參數的修改也類似,可以使用同樣的方式。 - 盡管在實驗中看到了修改參數成功了,但是操作始終有未知風險的,不能總是覺得有了這些工具,一定能夠萬無一失。
- 一定要嚴格遵守開發規范,數據庫的問題,往往是人在使用時的不當操作導致的。例如這個最大連接數,我們要評估好業務最大的并發的峰值,設置成比業務峰值大很多,就能盡量避免出現連接數打滿的問題了。
- 另外,該參數也不是設置得越大越好,需要評估物理資源并配合壓測情況得出一個合適的值,否則程序異常死鎖導致不斷申請新連接產生的連接數異常打滿時,可能直接把數據庫搞掛了。