连接MySQ时报错:Host X is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'

今天来了解一下performance_schema库中的 host_cache表。这个表记录了 host 的缓存内容,缓存信息包括主机名和 IP,用于避免 DNS 查找。这个表的记录,可以在需要的时候协助排查连接问题。

要开启这个功能,要保障参数 performance_schema的状态 是开启的。

另外,MySQL 启动时若带有参数–skip-name-resolve,或者配置文件里有参数skip-name-resolve,则,即使performance_schema=on,表 host_cache 也不会缓存主机信息。

 

前几天碰到一个问题,主要就是这个功能的基础导致的。

问题:

昨天开发同事在使用 MySQL 连接数据库的时候,客户端无法连接上数据库。当时数据库的时候报错如下:

Caused by: com.mysql.cj.exceptions.CJException: null,  message from server: "Host ' xxx' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'"

Caused by: com.mysql.cj.exceptions.CJException: null,  message from server: "Host 'xxx' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'" at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[?:1.8.0_66]

解决办法:

在调整 max_connect_erros 从 100 到 300以后,能连上数据库了:

mysql> show variables like '%max%connect%er%';
+--------------------+-------+
| Variable_name      | Value |
+--------------------+-------+
| max_connect_errors | 300   |
+--------------------+-------+
1 row in set (0.06 sec)

这是一个治标不治本的临时解决办法。

 

果然接着发生问题:

过了一段时间,开发同事表示应用服务器又连不上数据库了。报错如下:

Failed to initialize pool: Could not create connection to database server. Attempted reconnect 3 times. Giving up.
2019-10-21 10:26:03.021 main      
         ERROR o.s.b.SpringApplication 842 reportFailure - Application run failed org.springframework.context.
         ApplicationContextException: Unable to start web server;
nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat
……
Caused by: com.mysql.cj.exceptions.CJException: null,  message from server: "Host '92.168.225.131' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'"

解决办法:

最终处理办法,方法有多种:

mysql> flush hosts;
## 或者
mysql> truncate Performance_chema.host_cache;

或者找到mysqladmin

[root@my571 ~]#  whereis mysqladmin
mysqladmin: /usr/bin/mysqladmin /usr/share/man/man1/mysqladmin.1.gz
[root@my571 ~]# /usr/bin/mysqladmin flush-hosts  #清除hosts缓存

或者调整参数:

root@localhost|performance_schema> set global host_cache_size=0;

原因:

当时应用报这种错误的原因,其实是应用到 MySQL 服务器的网络延迟太大:

64 bytes from xxx: icmp_seq=50 ttl=64 time=24031 ms
64 bytes from xxx: icmp_seq=51 ttl=64 time=23008 ms
64 bytes from xxx: icmp_seq=52 ttl=64 time=21984 ms
64 bytes from xxx: icmp_seq=53 ttl=64 time=20960 ms
64 bytes from xxx: icmp_seq=54 ttl=64 time=19936 ms
64 bytes from xxx: icmp_seq=55 ttl=64 time=18912 ms
64 bytes from xxx: icmp_seq=56 ttl=64 time=17888 ms
64 bytes from xxx: icmp_seq=57 ttl=64 time=16864 ms
64 bytes from xxx: icmp_seq=58 ttl=64 time=15840 ms
64 bytes from xxx: icmp_seq=59 ttl=64 time=14815 ms

 

跟这种情况的报错的相关参数:max_connect_errors & connect_timeout。

数据库的connect_timeout = 10,网络延迟基本在 14 秒以上。参数max_connect_errors控制同一个 IP连接连续错误次数多过参数max_connect_errors的值时,这之后的连接mysql会阻止。

# 原文参考地址:

https://dev.mysql.com/doc/refman/5.6/en/blocked-host.html

The value of the max_connect_errors system variable determines how many successive interrupted connection requests are permitted. 

After max_connect_errors failed requests without a successful connection, mysqld assumes that something is wrong (for example, that someone is trying to break in),

 

解决这种问题的方法通常有以下几种:

1、调大 max_connect_errors;

2、flush hosts 或 mysqladmin flush-hosts 或者 truncate host_cache 表;

3、变量 host_cache_size 置为零。

方法一:只是延迟了这个错误再触发的阈值,当此 IP 再次连接 MySQL 失败次数达到参数max_connect_errors的新值,又会报同样的错误了。

方法二:是清理掉 MySQL 中记录的对应的IP主机相关cache记录,从零开始,达到 max_connect_errors 值大小,依旧会报错。

方法三:是临时禁用了host 的缓存功能,只是不记录 host cache 了,每次客户端连接,都会执行 DNS 查找。

# host  cache相关介绍官档连接
https://dev.mysql.com/doc/refman/5.7/en/host-cache.html

官方资料介绍,host_cache的字段SUM_CONNECT_ERRORS是统计被视为“阻塞”的连接错误的数量(根据max_connect_errors系统变量进行评估)。 只计算协议握手错误,并且仅用于通过验证的主机(HOST_VALIDATED = YES)。

MySQL客户端与数据库建立连接需要发起三次握手协议,正常情况下,这个时间非常短,但是一旦网络异常,网络超时等因素出现,就会导致这个握手协议无法完成,

MySQL有个参数connect_timeout,它是MySQL服务端进程mysqld等待连接建立完成的时间,单位为秒。如果超过connect_timeout时间范围内,仍然无法完成协议握手话,MySQL客户端会收到异常,异常消息类似于: Lost connection to MySQL server at 'XXX', system error: errno,该变量默认是10秒。

参数--skip-host-cache的功能类似于 设置参数 host_cache_size=0,但是 host_cache_size更灵活。 host_cache_size能在 MySQL运行时通过修改全局参数调整是否缓存、缓存的大小。

即使启动 MySQL 服务时,加上了--skip-host-cache参数,在数据库运行时也是可以如常修改参数host_cache_size的值,只不过修改不会生效。

 

 

以下来验证 host_cache 中 sum_connect_errors 列的值与 max_connect_errors 参数:

1、主机名my 571 的为 MySQL 服务器,IP:131;主机名为 my80的做应用客户端,IP:129。

构造网络延迟的场景验证:

[root@my80 ~]# tc qdisc add dev eth0 root netem delay 11000ms

2、此时从 my80 上 ping MySQL 服务器:

[root@my80 ~]#  ping 192.168.225.131

PING 192.168.225.131 (192.168.225.131) 56(84) bytes of data.
64 bytes from 192.168.225.131: icmp_seq=1 ttl=64 time=11000 ms
64 bytes from 192.168.225.131: icmp_seq=2 ttl=64 time=11001 ms
64 bytes from 192.168.225.131: icmp_seq=3 ttl=64 time=11001 ms
64 bytes from 192.168.225.131: icmp_seq=4 ttl=64 time=11001 ms
64 bytes from 192.168.225.131: icmp_seq=6 ttl=64 time=11001 ms
64 bytes from 192.168.225.131: icmp_seq=7 ttl=64 time=11001 ms
64 bytes from 192.168.225.131: icmp_seq=5 ttl=64 time=11001 ms
64 bytes from 192.168.225.131: icmp_seq=6 ttl=64 time=11001 ms

延迟基本是 11 秒左右,目前 my571 的数据库的参数 connect_timeout =10,连接是会超时的。

3、my80 上连接 MySQL 服务器,仅执行一次:

[root@my80 ~]# mysql -h192.168.225.131 -uroot -proot
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 2026 (HY000): SSL connection error: error:00000000:lib(0):func(0):reason(0)
[root@my80 ~]#

4、查看此时的host_cache 表,结果如下:

此时:sum_connect_errors=1,count_handshake_errors=1。

5、此时继续在my80 上反复登录3次,报错如下:

[root@my80 ~]# mysql -h192.168.225.131 -uroot -proot
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 2026 (HY000): SSL connection error: error:00000000:lib(0):func(0):reason(0)
[root@my80 ~]#
[root@my80 ~]# mysql -h192.168.225.131 -uroot -proot
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 2026 (HY000): SSL connection error: error:00000000:lib(0):func(0):reason(0)
[root@my80 ~]#
[root@my80 ~]# mysql -h192.168.225.131 -uroot -proot
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 2026 (HY000): SSL connection error: error:00000000:lib(0):func(0):reason(0)
[root@my80 ~]#

虽然报错连不上,但是还未出现“ Host '192.168.225.129' is blocked ”。因为当前连续的失败连接数未草果参数 max_connect_errors 的值大小。

此时日志报错信息如下:

2019-10-22T07:51:30.427453Z 11 [Note] Got timeout reading communication packets

6、查看当前参数 max_connect_errors=1+3;当前对应的 host_cache 表记录,如下:

由于参数 connect_timeout=10,网络延时超过10秒,导致连接MySQL失败。

在新增一次失败连接后,MySQL服务器上查询host_cache表的话,就会看到SUM_CONNECT_ERRORS变大 了,在原来的值上加 1,COUNT_HANDSHAKE_ERRORS也变大了1。

7、继续执行,再进行 3 次:

可以看到这次的“三次”连接都报错:“ Host '192.168.225.129' is blocked ”了。

此时仍然,sum_connect_errors=4 && count_handshake_errors=4,均等于 max_connect_errors 参数的设定值,大于这个值的连接都会被拒绝掉,sum_connect_errors 不会变更大,后面三次被拒绝因此报错 “ Host '192.168.225.129' is blocked ”。

此报错的解决办法:

8、然后再在 my80 上尝试登录 my571 的 MySQL:

虽然由于延迟变大,超过 mysql571 的connect_timeout 的限制,但是并未再报错“host xxx is blocked” 了。解决延迟后,就可以继续正常连接数据库了。

9、测试完成后,记得解除延迟 10s 的设置:

[root@my80 ~]# tc qdisc del dev ens33 root netem delay 11000ms


 

额外,参数 count_authentication_errors。

另外,从上面测试案例中看到的 host_cache 表中有一个字段“count_authentication_errors”,这个字段跟 sum_connect_errors 有的人可能会弄混淆。count_authentication_errors 记录的是来自客户端的连接中、输入密码错误的次数。

 

开始测试连接 MySQL 数据库中 count_authentication_errors的变化:

1、先清空 host_cache 的记录:

2、在 my80 上,执行多次错入的密码的数据库连接命令:

3、在 my571 上进入数据库查看表 host_cache:

此时,count_authentication_errors=7,

4、此时数据库相对的错误日志如下:

2019-10-13T07:37:25.282600Z 3 [Warning] IP address '192.168.225.129' could not be resolved: Name or service not known
2019-10-13T07:37:25.308431Z 3 [Note] Access denied for user 'iris'@'192.168.225.129' (using password: YES)
2019-10-13T07:37:26.821914Z 4 [Note] Access denied for user 'iris'@'192.168.225.129' (using password: YES)
2019-10-13T07:37:29.060450Z 5 [Note] Access denied for user 'iris'@'192.168.225.129' (using password: YES)
2019-10-13T07:37:31.075948Z 6 [Note] Access denied for user 'iris'@'192.168.225.129' (using password: YES)
2019-10-13T07:37:32.626528Z 7 [Note] Access denied for user 'iris'@'192.168.225.129' (using password: YES)
2019-10-13T07:37:34.258874Z 8 [Note] Access denied for user 'iris'@'192.168.225.129' (using password: YES)
2019-10-13T07:37:36.540025Z 9 [Note] Access denied for user 'iris'@'192.168.225.129' (using password: YES)

 

总结

本次我们环境的数据库报错,是因为网络环境不好,导致完成连接数据库的时间(即三次握手协议完成的时长)超过MySQL 中定义的参数的 connect_timeout 的值,应用服务器不断尝试连接,最终尝试次数超过了 MySQL 的参数 max_connect_errors 的大小,导致的报错。

参数max_connect_errors决定了 MySQL 允许的每个 IP 持续连接数据库时发生连接错误的次数,对应的是表 host_cache 中的字段 sum_connect_errors 的值的大小,同时也跟 count_handshake_errors 相关;

表host_cache中字段 count_authentication_errors 的值大小,表示连接数据库时使用了错误的密码的次数。目前好像没有参数,可以使用 MySQL 插件控制。

 

 

 

 

<think> 我们面对的核心问题是:使用 `systemctl stop mysq` 命令出现连接和认证失败,导致无法停止 mysq.service 服务。结合之前的错误信息,我们将从权限、服务状态、进程管理三个维度展开解决方案。 ### 一、问题根源定位 ```mermaid graph TD A[systemctl stop mysq失败] --> B[权限认证失败] A --> C[连接] B --> D[当前用户不在sudoers] C --> E[系统策略服务polkit异常] C --> F[MySQL服务无响应] ``` ### 二、分步解决方案 #### 1. 权限问题(Authentication failure) **现象**: `polkit-agent-helper-1: pam_authenticate failed: Authentication failure` **原因**: - 当前用户 `bzwjj` 无管理员权限 - 未正确配置 sudo 权限 **解决方法**: ```bash # 方法1:切换到root用户操作 su - # 输入root密码 systemctl stop mysql # 注意服务名可能为mysql而非mysq # 方法2:临授权用户(需root权限执行) usermod -aG sudo bzwjj # 将用户加入sudo组 # 重新登录后执行 sudo systemctl stop mysql ``` > ⚠️ **关键细节**: > 若忘记 root 密码,需进入恢复模式修改[^3]: > 1. 重启系统长按 Shift 进入 GRUB 菜单 > 2. 选择 `Advanced options > Recovery mode > root` > 3. 执行 `passwd root` 重置密码 #### 2. 服务名称错误(连接诱因) **现象**: `Failed to stop mysq.service: Connection timed out` **诊断**: - 系统实际注册的服务名通常为 `mysql` 或 `mysqld` - 错误名称 `mysq` 导致超 **验证服务名**: ```bash systemctl list-unit-files | grep -E 'mysql|mariadb' # 正确输出示例 # mysql.service enabled # mariadb.service disabled ``` **重启正确服务**: ```bash sudo systemctl stop mysql # 最常见名称 sudo systemctl stop mysqld # 次要常见名称 ``` #### 3. MySQL 进程僵死(强制终止方案) **适用场景**: 当服务状态显示 `inactive` 但进程仍在运行 **操作步骤**: ```bash # 查找所有MySQL相关进程 ps aux | grep -i 'mysqld\|mysql_safe' # 强制终止进程树 sudo pkill -9 -f mysqld # 或精确终止 sudo kill -9 $(pgrep mysqld) ``` #### 4. 系统策略服务异常(polkit修复) **适用场景**: 反复出现 `polkit-agent-helper-1` 认证错误 **修复命令**: ```bash # 重启账户系统服务 sudo systemctl restart accounts-daemon.service # 重置策略缓存 sudo polkitd --debug ``` ### 三、服务状态验证矩阵 | 验证方法 | 成功标志 | 失败标志 | |-------------------|----------------------------------|--------------------------| | `systemctl status` | Active: inactive (dead) | Active: active (running) | | `netstat 3306` | 无3306端口监听 | 0.0.0.0:3306 LISTEN | | `ps aux` | 无 mysqld 进程 | /usr/sbin/mysqld 存在 | ### 四、高级故障排除 **场景:服务文件损坏** ```bash # 重新加载服务配置 sudo systemctl daemon-reload # 重注册MySQL服务(需MySQL安装包) sudo mysql_install_db sudo mysqld --initialize ``` **场景:磁盘空间不足** ```bash df -h # 检查/var/log空间 journalctl --vacuum-size=200M # 清理日志 ``` ### 五、备份操作修正 原命令错误: ```bash cp -R /var/lib/mysql /backup/mysql_full_$(date +%F) ``` **正确操作**: ```bash # 创建备份目录 sudo mkdir -p /backup # 带压缩备份(避免权限问题) sudo tar -czvf /backup/mysql_full_$(date +%F).tar.gz /var/lib/mysql ``` --- §§ 相关问题 §§ 1. 如何永久解决 `polkit-agent-helper-1` 认证失败问题? 2. 当 `systemctl stop mysql` 超,有哪些替代停止方案? 3. 强制终止 MySQL 进程是否会导致数据损坏?如何安全恢复? 4. 如何验证 MySQL 服务名称在系统中的注册状态? 5. 在无 systemd 的 Linux 系统中如何停止 MySQL 服务? </think> ### 解决 systemctl stop mysq 连接和认证失败问题 #### 一、问题核心原因分析 ```mermaid graph TD A[停止失败] --> B[权限问题] A --> C[服务名称错误] A --> D[系统策略服务异常] B --> E[用户不在sudoers] C --> F[服务名应为mysql] D --> G[polkit认证故障] ``` #### 二、具体解决方案 1. **权限问题修正(关键步骤)** ```bash # 切换到root用户 su - # 将当前用户加入sudo组(需root权限) usermod -aG sudo bzwjj ``` - 重新登录后使用 `sudo systemctl stop mysql` - 验证权限:`groups bzwjj` 应包含 `sudo` 组 2. **服务名称校正** ```bash # 检查实际服务名(通常为mysqlmysqld) systemctl list-unit-files | grep -i mysql # 正确停止命令(90%场景) sudo systemctl stop mysql # 备用停止命令 sudo systemctl stop mysqld ``` 3. **系统策略服务修复** ```bash # 重启账户系统服务 sudo systemctl restart accounts-daemon.service # 重置策略缓存 sudo polkitd --debug ``` #### 三、MySQL进程强制终止方案 当服务无响应: ```bash # 查找MySQL进程ID ps aux | grep mysqld # 强制终止进程 sudo kill -9 $(pgrep mysqld) # 验证进程终止 pgrep mysqld # 无输出表示成功 ``` #### 四、备份操作修正 原命令错误原因:`/backup` 目录不存在 ```bash # 创建备份目录 sudo mkdir -p /backup # 执行带权限的备份 sudo cp -R /var/lib/mysql /backup/mysql_full_$(date +%F) ``` #### 五、服务状态验证矩阵 | 验证方法 | 成功标志 | 失败标志 | |-------------------|----------------------------------|--------------------------| | `systemctl status` | Active: inactive (dead) | Active: active (running) | | `netstat -tuln` | 无3306端口监听 | 0.0.0.0:3306 LISTEN | | `ps aux` | 无 mysqld 进程 | /usr/sbin/mysqld 存在 | > 📌 **关键提示**:MySQL 8.0 默认服务名在 Ubuntu 上是 `mysql`,在 CentOS 上是 `mysqld`[^1] #### 六、高级调试方案 ```bash # 查看详细错误日志 journalctl -u mysql --since "5 minutes ago" # 检查SELinux状态(若启用需调整策略) sestatus sudo setsebool -P httpd_can_network_connect_db 1 ``` ---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值