这是认证阶段拒绝,非网络问题;SELECT USER(), CURRENT_USER()可暴露真实匹配账号,前者为客户端声明身份,后者为MySQL实际认证账号,权限生效以CURRENT_USER()为准。

这不是网络不通,是MySQL在认证阶段就拒绝了连接请求——它压根没让你走到输密码那步。
SELECT USER(), CURRENT_USER() 能立刻暴露真实匹配来源
执行这条语句,会返回两列:USER() 是客户端声明的身份(比如你 JDBC URL 里写的 host),CURRENT_USER() 是 MySQL 实际查 mysql.user 表后认定的账号。两者常不一致:
-
USER()可能是'app'@'192.168.5.22'(你本机 IP) -
CURRENT_USER()却是'app'@'localhost'(因为 DNS 反解出主机名,而 MySQL 没配skip_name_resolve)
真正起作用的是后者。所以别只看 JDBC URL 写的 IP,得用 CURRENT_USER() 确认 MySQL 到底“认”你哪个 host。
GRANT 语句比 UPDATE mysql.user 安全且可靠
直接 UPDATE mysql.user 表风险高,容易覆盖已有记录、漏掉权限字段、或忽略认证插件变更(尤其 MySQL 8+)。正确做法是用 GRANT:
安装、修复、更新或打包一个基于 Python 和 PyMySQL 实现的 Windows `mysql` 命令。适用于用户希望在 PowerShell/CMD 中输入 `mysql` 时重定向到 Python 实现、需要交互式输入 MySQL 连接信息、需要同步到当前用户本地 bin 目录,或需要将该能力封装成可公开复用的 Codex skill。
- 允许特定 IP:
GRANT SELECT, INSERT ON mydb.* TO 'myuser'@'192.168.5.22' IDENTIFIED BY 'pwd'; - 允许子网:
GRANT ALL ON mydb.* TO 'myuser'@'192.168.5.%'; - 禁止对 root@% 授权——生产环境必须用专用账号
执行完必须跟 FLUSH PRIVILEGES;,否则内存缓存不会更新。
bind-address = 0.0.0.0 不等于“就能连上”
即使 bind-address 改对了,还有三道关卡可能拦住你:
- 系统防火墙:Ubuntu 用
sudo ufw allow 3306/tcp,CentOS 用firewall-cmd --add-port=3306/tcp - 云平台安全组:阿里云/腾讯云控制台必须单独放行 3306 入方向,且源 IP 不能写 0.0.0.0/0(除非测试)
- DNS 解析干扰:如果没设
skip_name_resolve=ON,MySQL 会尝试反向解析客户端 IP 成主机名,一旦 DNS 故障或配置不对,host字段就变成'client-abc.example.com'而非 IP,导致授权失效
最易被忽略的是 DNS 解析行为——它让 host 值变得不可控,而多数教程从不提 skip_name_resolve 这个开关。










