本文主要記錄了MySQL管理端口無法登錄的排查過程,以及預防 too many connections 的一些建議。
作者:呂虎橋
愛可生DBA 團隊成員,主要負責 DMP 平臺和 MySQL 數據庫的日常運維及故障處理。
本文來源:原創投稿
- 愛可生開源社區出品,原創內容未經授權不得隨意使用,轉載請聯繫小編並註明來源。
背景描述
MySQL 8.0.14 版本中引入了 admin_port
參數,用於提供一個管理端口來處理 too many connections
報錯。最近一套 MySQL 8.0 實例出現 too many connections
報錯,嘗試通過管理端口登錄,但是仍然提示該報錯。跟業務部門協商之後,調大了連接數,重啓數據庫恢復業務。爲什麼配置了 admin_port
卻沒有生效呢,帶着疑問做了如下測試。
場景復現
管理端口相關參數
--創建一個單獨的 listener 線程來監聽 admin 的連接請求
create_admin_listener_thread = 1
--監聽地址
admin_address = localhost
--監聽端口,默認爲 33062,也可以自定義端口
admin_port = 33062
--配置好參數,重啓數據庫生效
systemctl restart mysqld_3306
--測試 root 賬號是否可以通過 33062 端口登錄
[root@mysql ~]# mysql -uroot -p -S /data/mysql/data/3306/mysqld.sock -P33062 -e 'select version()'
Enter password:
+-----------+
| version() |
+-----------+
| 8.0.33 |
+-----------+
模擬故障現象
調小 max_connections
參數,模擬出現 too many connections
報錯。
--更改 max_connections 參數爲 1
mysql> set global max_connections = 1;
--模擬連接數被打滿
[root@mysql ~]# mysql -uroot -p -S /data/mysql/data/3306/mysqld.sock -e 'select version()'
Enter password:
ERROR 1040 (HY000): Too many connections
--root 賬號使用 33062 端口登錄依然報錯
[root@mysql ~]# mysql -uroot -p -S /data/mysql/data/3306/mysqld.sock -P33062 -e 'select version()'
Enter password:
ERROR 1040 (HY000): Too many connections
故障分析
疑問
爲啥連接數沒打滿的情況下,root
賬號可以通過 33062 端口登錄?
[root@mysql ~]# mysql -uroot -p -S /data/mysql/data/3306/mysqld.sock -P33062
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 16
Server version: 8.0.33 MySQL Community Server - GPL
Copyright (c) 2000, 2023, 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> \s
--------------
mysql Ver 8.0.33 for Linux on x86_64 (MySQL Community Server - GPL)
Connection id: 16
Current database:
Current user: root@localhost
SSL: Not in use
Current pager: stdout
Using outfile: ''
Using delimiter: ;
Server version: 8.0.33 MySQL Community Server - GPL
Protocol version: 10
Connection: Localhost via UNIX socket --使用的socket連接
Server characterset: utf8mb4
Db characterset: utf8mb4
Client characterset: utf8mb4
Conn. characterset: utf8mb4
UNIX socket: /data/mysql/data/3306/mysqld.sock
Binary data as: Hexadecimal
Uptime: 1 hour 6 min 54 sec
Threads: 3 Questions: 25 Slow queries: 0 Opens: 142 Flush tables: 3 Open tables: 74 Queries per second avg: 0.006
socket 連接會忽略指定的端口,即便是指定一個不存在的端口也是可以登錄的,也就是說 socket 連接並沒有通過管理端口登錄,所以在連接數打滿的情況下,使用 socket 登錄依然會報錯。
[root@mysql ~]# netstat -nlp |grep 33063
[root@mysql ~]# mysql -uroot -p -S /data/mysql/data/3306/mysqld.sock -P33063 -e 'select version()'
Enter password:
+-----------+
| version() |
+-----------+
| 8.0.33 |
+-----------+
登錄地址
netstat
查看 33062 端口是監聽在 127.0.0.1
,並不是參數裏邊配置的 localhost
。
[root@mysql ~]# netstat -nlp |grep 33062
tcp 0 0 127.0.0.1:33062 0.0.0.0:* LISTEN 2204/mysqld
查看 MySQL 官方文檔發現 admin_address
支持設置爲 IPv4、IPv6 或者 hostname。如果該值是主機名,則服務器將該名稱解析爲 IP 地址並綁定到該地址。如果一個主機名可以解析多個 IP 地址,如果有 IPv4 地址,服務器使用第一個 IPv4 地址,否則使用第一個 IPv6 地址,所以這裏把 localhost
解析爲了 127.0.0.1
。
If admin_address is specified, its value must satisfy these requirements:
- The value must be a single IPv4 address, IPv6 address, or host name.
- The value cannot specify a wildcard address format (*, 0.0.0.0, or ::).
- As of MySQL 8.0.22, the value may include a network namespace specifier.
An IP address can be specified as an IPv4 or IPv6 address. If the value is a host name, the server resolves the name to an IP address and binds to that address. If a host name resolves to multiple IP addresses, the server uses the first IPv4 address if there are any, or the first IPv6 address otherwise.
指定 admin_address
爲主機名,測試效果。
--修改 admin_address 值爲主機名 mysql
vim /data/mysql/etc/3306/my.cnf
admin_address = mysql
--hosts 配置
[root@mysql ~]# grep -i mysql /etc/hosts
192.168.100.82 mysql
--重啓數據庫
systemctl restart mysql_3306
--查看管理端口監聽的地址,監聽地址變更爲主機名 mysql 對應的IP地址
[root@mysql ~]# netstat -nlp |grep 33062
tcp 0 0 192.168.100.82:33062 0.0.0.0:* LISTEN 1790/mysqld
再次嘗試
嘗試使用 127.0.0.1
地址登錄。
--root 賬號無法通過 127.0.0.1 地址登錄,因爲沒有授權 root 賬號從 127.0.0.1 地址登錄
[root@mysql ~]# mysql -uroot -p -h127.0.0.1 -P33062 -e 'select version()'
Enter password:
ERROR 1130 (HY000): Host '127.0.0.1' is not allowed to connect to this MySQL server
--默認 root 賬號只允許從 localhost 登錄
mysql> select user,host from mysql.user where user='root';
+------+-----------+
| user | host |
+------+-----------+
| root | localhost |
+------+-----------+
故障解決
設置 admin_address
爲 127.0.0.1
,並添加管理賬號。
--創建一個單獨的 listener 線程來監聽 admin 的裏連接請求
create_admin_listener_thread = 1
--監聽地址,建議設置爲一個固定的 IP 地址
admin_address = 127.0.0.1
--監聽端口,默認爲 33062,也可以自定義端口
admin_port = 33062
--新建管理賬號
create user root@'127.0.0.1' identified by 'xxxxxxxxx';
grant all on *.* to root@'127.0.0.1' with grant option;
flush privileges;
--測試登陸成功
[root@mysql ~]# mysql -uroot -p -h127.0.0.1 -P33062 -e 'select version()'
Enter password:
+-----------+
| version() |
+-----------+
| 8.0.33 |
+-----------+
MySQL 管理端口配置總結
- 通過
admin_address
設置爲固定的 IP 地址,例如127.0.0.1
,避免設置爲hostname
引起的不確定因素。 - MySQL 部署好之後,新建可以通過
admin_address
地址登錄的管理員賬號,例如root@'127.0.0.1'
。
一些優化建議
- 最小化權限配置,除管理員之外其他賬號一律不允許配置
super
或者service_connection_admin
權限。 - 應用端(Tomcat、JBoss 、Wildfly 等)配置數據源連接池,聲明
initialSize
、maxActive
屬性值,控制連接數的無限增長。 - 及時優化 SQL,防止因性能問題引起的併發操作導致數據庫連接數打滿。
關於 SQLE
愛可生開源社區的 SQLE 是一款面向數據庫使用者和管理者,支持多場景審覈,支持標準化上線流程,原生支持 MySQL 審覈且數據庫類型可擴展的 SQL 審覈工具。