Skip to content

一、背景

生产环境下遇到一个问题,有数据库节点的连接数略高,触发了连接数告警。登录上查看后,发现实际业务压力不大。查看 processlist 发现有大量状态为 Waiting in connection_control plugin 的等待连接。

bash
mysql> select ID,HOST,DB,COMMAND,TIME,STATE,INFO from information_schema.PROCESSLIST where STATE='Waiting in connection_control plugin';

该状态的连接总数达到 338 个:

bash
mysql> select COUNT(*) from information_schema.PROCESSLIST where STATE='Waiting in connection_control plugin';

应该是 Connection-Control Plugins 起作用了,先在测试环境模拟一下。

二、模拟测试

2.1 安装

Connection-Control Plugins 插件默认未启用,需要自行安装:

bash
mysql> INSTALL PLUGIN CONNECTION_CONTROL SONAME 'connection_control.so';
Query OK, 0 rows affected (0.40 sec)
mysql> INSTALL PLUGIN CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS SONAME 'connection_control.so';
Query OK, 0 rows affected (0.01 sec)

确认 SQL 插件是否安装:

bash
mysql> select PLUGIN_NAME, PLUGIN_STATUS from INFORMATION_SCHEMA.PLUGINS where PLUGIN_NAME like 'connection%';
+------------------------------------------+---------------+
| PLUGIN_NAME                              | PLUGIN_STATUS |
+------------------------------------------+---------------+
| CONNECTION_CONTROL                       | ACTIVE        |
| CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS | ACTIVE        |
+------------------------------------------+---------------+
2 rows in set (0.00 sec)

2.2 参数释疑

bash
mysql> show variables like "connection_control%";
+-------------------------------------------------+------------+
| Variable_name                                   | Value      |
+-------------------------------------------------+------------+
| connection_control_failed_connections_threshold | 3          |
| connection_control_max_connection_delay         | 2147483647 |
| connection_control_min_connection_delay         | 1000       |
+-------------------------------------------------+------------+
3 rows in set (0.00 sec)

参数含义:

  • connection_control_failed_connections_threshold:单个用户登录失败(由于密码错误引起)次数上限,默认 3 次
  • connection_control_max_connection_delay:失败上限之后再次尝试登录前最大等待时间,单位 ms
  • connection_control_min_connection_delay:失败上限之后再次尝试登录前最小等待时间,单位 ms

上述 3 个参数均可以利用 set global 的方式在线修改。

2.3 实验

尝试 3 次错误输入密码后,在第 4 次登录时会 delay 1 秒(由 connection_control_min_connection_delay 指定),同时 Connection_control_delay_generated 计数 +1。若登录密码继续输入错误,则 delay 秒数与计数器继续增加,直到成功登录为止,此时 delay 清零。

查看到登录失败的次数:

bash
mysql> show global status like "%conn%control%";
+------------------------------------+-------+
| Variable_name                      | Value |
+------------------------------------+-------+
| Connection_control_delay_generated | 1     |
+------------------------------------+-------+
1 row in set (0.00 sec)

开启多个连接,继续试错下去,此时可以看到进程中:

bash
mysql> select * from information_schema.PROCESSLIST where USER='root';
+----+------+-----------+------+---------+------+--------------------------------------+------+---------+-----------+---------------+
| ID | USER | HOST      | DB   | COMMAND | TIME | STATE                                | INFO | TIME_MS | ROWS_SENT | ROWS_EXAMINED |
+----+------+-----------+------+---------+------+--------------------------------------+------+---------+-----------+---------------+
| 54 | root | localhost | NULL | Connect |    2 | Waiting in connection_control plugin | NULL |    2485 |         0 |             0 |
| 52 | root | localhost | NULL | Connect |    7 | Waiting in connection_control plugin | NULL |    7038 |         0 |             0 |
| 53 | root | localhost | NULL | Connect |    4 | Waiting in connection_control plugin | NULL |    4591 |         0 |             0 |
+----+------+-----------+------+---------+------+--------------------------------------+------+---------+-----------+---------------+
3 rows in set (0.00 sec)

这时,我们就回到了一开始提出的生产环境下遇到的问题。

三、解决生产问题

由于问题连接过多,逐个 kill 掉显然不太现实。

因此,采用拼接 SQL 的方式,批量 kill:根据 STATE 状态为 Waiting in connection_control plugin,从 information_schema.PROCESSLIST 表中检索出 ID,再在本地文本中拼接出 SQL,再批量 kill

bash
mysql> select ID from information_schema.PROCESSLIST where Command='Connect' and STATE='Waiting in connection_control plugin';

执行 SQL 文件后,连接数告警消失,问题暂时解决。

四、事后分析

后续排查确认是 zabbix agent 的一个监控脚本,数据库地址配置的问题,导致存在这样的现象:Waiting in connection_control plugin

补充:

  • 卸载 MySQL 安全插件:Connection-Control Plugins
  • 注意查看 my.cnf 中是否也定义了此参数
bash
mysql> UNINSTALL PLUGIN CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS;
mysql> UNINSTALL PLUGIN CONNECTION_CONTROL;
最近更新