在做 DBA 的这些年里,我处理过各种各样的数据库问题。我遇到的最常见问题之一就是——ERROR 1040 (08004): Too many connections 相关的一些问题,这个错误可以说众所周知;关于这个错误已经有很多文章了,尽管如此用户还是不断掉入这个问题的陷阱,这可能是因为数据库配置不当、应用程序组件发生变化,或者只是因为应用程序中的连接突然增加所导致的。在某些时候,我们可能都会在工作中遇到这个问题,而且可能还不止一次遇到。这篇文章的主要目的是研究 MySQL 8 新提供的 administrative connections 特性,使用这些管理连接可以在出现这个问题时无需重启数据库实例。
默认行为
我们知道数据库中允许创建的连接数是由 max_connections 参数定义的,这个参数的默认值是 151,并且支持动态调整,这意味着无需重启数据库实例就可以调整连接数。如果数据库中的连接数达到最大值,我们将看到这个糟糕的错误——ERROR 1040 (08004): Too many connections。重要的是还要记住一个开箱即用功能,MySQL 允许创建一个额外的连接,这个连接是为 SUPER 权限(已废弃这里)或 CONNECTION_ADMIN 权限的用户保留的。
我准备用一个示例演示这个功能,对于这个示例需要创建一个 max_connections=20 的数据库实例,并创建三个用户,用户 monitor1 只有 PROCESS 权限,用户 admin1 拥有 PROCESS 和 CONNECTION_ADMIN 权限,最后一个用户 admin2 拥有超级用户权限(已废弃)。我们将演示 MySQL 在用户连接数达到最大值的情况下如何处理这些连接:
-- execute all 20 concurrent connections sysbench oltp_read_write --table-size=1000000 --db-driver=mysql --mysql-host=localhost --mysql-db=sbtest --mysql-user=root --mysql-password="***" --num-threads=20 --time=0 --report-interval=1 run -- test with user monitor1 [root@rocky-test1 ~]# mysql -u monitor1 -p Enter password: ERROR 1040 (08004): Too many connections
-- test with user admin1 [root@rocky-test1 ~]# mysql -u admin1 -p Enter password: Welcome to the MySQL monitor. Commands endwith ; or g. Your MySQL connection id is144 Server version: 8.0.29-21 Percona Server (GPL), Release21, Revision c59f87d2854
Copyright (c) 2009-2022 Percona LLC and/or its affiliates 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.
-- test with user admin2 [root@rocky-test1 ~]# mysql -u admin2 -p Enter password: Welcome to the MySQL monitor. Commands endwith ; or g. Your MySQL connection id is145 Server version: 8.0.29-21 Percona Server (GPL), Release21, Revision c59f87d2854
Copyright (c) 2009-2022 Percona LLC and/or its affiliates 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>show grants; +------------------------------------+ | Grants for admin2@%| +------------------------------------+ |GRANT SUPER ON*.*TO `admin2`@`%` | +------------------------------------+ 1rowinset (0.00 sec)
正如我们所演示的,MySQL 允许拥有 CONNECTION_ADMIN 或者 SUPER 权限的用户进行连接;所以当用户 monitor1 尝试进行连接时是不允许的,因为它没有被授予这些权限。一旦我们获得了对数据库的访问权限,我们就可以通过在线更改参数 max_connections 轻松增加连接数量,然后再继续排查导致连接数量不够问题的根本原因。重要的是要记住只是授予这些权限的用户连接才可以执行这个操作,所以不要轻易将这些权限授予某个用户,否则我们仍然可能被锁定在数据库之外。
1 2 3 4 5
– trying a second connection withuser admin1
[root@rocky-test1 ~]# mysql -u admin1 -p Enter password: ERROR 1040 (HY000): Too many connections
通常出现这个问题时,我们是无法访问 MySQL 数据库的,紧急的处理方式是重启数据库实例并处理由此所导致的一些问题,但是嘿……这会导致业务系统在正常运行时有几分钟时间无法连接到数据库;还有另一种获取数据库访问权限的方法,即使用 GDB 工具,但这个办法并一定是可行的,Too many connections? No problem!是我过去写的一篇关于这个工具的文章,文章有点久了但这个办法仍然有效。
Percona Server 为 MySQL 和 MariaDB 边注说明
Percona Server for MySQL 在 MySQL 8.0.14 之前的版本中,有另一种访问数据库实例的方法,与 MySQL 8.0.14 版本中引入的新功能类似,它是通过启用变量 extra_port 和 extra_max_connections 来实现的,这些变量的使用超出了这篇博文的范围,这些变量的目的同样是在数据库的最大连接数已经达到上限的情况下允许继续连接到数据库。不过需要记住,这些变量已在 MySQL 8.0.14 版本中删除,如果在配置文件中出现这些变量,MySQL 数据库实例将无法正常启动并显示错误信息。与 Percona Server for MySQL 一样,MariaDB 数据库对这些变量也有类似的实现。MariaDB 的文档可以在这里找到。
启用 Administrative Connections 最简单的方式是设置 admin_address 参数,这是管理连接将会监听的 IP 地址;例如,如果我们只允许本地连接,我们可以将这个参数设置为 127.0.0.1,或者如果我们想通过网络进行连接,我们可以将这个变参数定义为服务器的 IP 地址。这个参数不能够动态设置,这意味着修改这个参数需要重启数据库;默认情况下,此参数值为空,表示禁用管理连接功能。另一个相关参数是 admin_port,此参数定义 MySQL 为管理连接所提供的监听端口,此参数的默认值为 33062,定义这两个参数并重启数据库实例后,我们将会在错误日志中看到一条消息,显示管理接已准备好并等待连接:
[root@rocky-test1 ~]# mysql -h 127.0.0.1-P 33062-u admin1 -p Enter password: Welcome to the MySQL monitor. Commands endwith ; or g. Your MySQL connection id is23 Server version: 8.0.29-21 Percona Server (GPL), Release21, Revision c59f87d2854
Copyright (c) 2009-2022 Percona LLC and/or its affiliates 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> s -------------- mysql Ver 8.0.29-21for Linux on x86_64 (Percona Server (GPL), Release21, Revision c59f87d2854)
Connection id: 23 Current database: Currentuser: admin1@localhost SSL: Cipher in use is TLS_AES_256_GCM_SHA384 Current pager: stdout Using outfile: '' Using delimiter: ; Server version: 8.0.29-21 Percona Server (GPL), Release21, Revision c59f87d2854 Protocol version: 10 Connection: 127.0.0.1 via TCP/IP Server characterset: utf8mb4 Db characterset: utf8mb4 Client characterset: utf8mb4 Conn. characterset: utf8mb4 <strong>TCP port: 33062</strong> Binary data as: Hexadecimal Uptime: 50 min 27 sec
[root@rocky-test1 ~]# mysql -h 127.0.0.1-P 33062-u admin2 -p Enter password: <strong>ERROR 1227 (42000): Access denied; you need (at least oneof) the SERVICE_CONNECTION_ADMIN privilege(s) for this operation</strong>
总结
如果我们使用的是 MySQL 8.0.14 或更高版本,我们应用启用管理连接功能;正如示例所见开启这个能非常简单,使用这个新特性在触发 ERROR 1040 (08004): Too many connections 错误时允许 DBA 继续访问数据库。这个新特性不会影响正常的数据库性能,但是可以对 DBA 工作发挥很大作用。
我们应当考虑仅向管理员用户添加 SERVICE_CONNECTION_ADMIN 权限,而不是普通应用程序用户,这样做的目的是不要滥用此功能。如果我们还在使用较低版本的 Percona Server for MySQL 时,如果遇到最大连接问题,我们可以配置参数 extra_port 和 extra_max_connections 来访问数据库。
[percona@test9 msb_5_0_87]$ ./use Welcome to the MySQL monitor. Commands endwith ; or \g. Your MySQL connection id is8 Server version: 5.0.87-percona-highperf-log MySQL Percona High Performance Edition, Revision 61 (GPL)
Type 'help;'or'\h'for help. Type '\c'to clear the current input statement.