“Access denied”是MySQL拒绝'user'@'host'组合连接,未进入密码校验;需确认User/Host精确匹配('localhost'≠'127.0.0.1'),检查mysql.user表、FLUSH PRIVILEGES生效、bind_address、防火墙及认证插件兼容性。

“Access denied”不是密码错了,而是 MySQL 明确拒绝了你这个 'user'@'host' 组合的连接请求——它压根没走到校验密码那步。
查清楚你连的是哪个 'user'@'host' 组合
错误信息里写的 'root'@'192.168.1.100' 或 'app'@'localhost' 就是关键。MySQL 把它们当完全不同的账号处理:
- 执行
SELECT User, Host FROM mysql.user;,看结果里有没有和你连接时一模一样的User和Host字段(注意:'localhost'≠'127.0.0.1',Unix socket 和 TCP 是两套路径) - 如果只看到
'root'@'localhost',但从命令行用mysql -h 127.0.0.1 -u root连,就会被拒——得额外加一条'root'@'127.0.0.1' - 远程连接必须显式存在
'user'@'%'或'user'@'192.168.1.%',不能靠“本地能连”来推断
授权后忘记 FLUSH PRIVILEGES; 是高频失手点
用 GRANT 创建用户通常自动生效,但直接 INSERT 或 UPDATE mysql.user 表后,不执行这句权限不会加载:
安装、修复、更新或打包一个基于 Python 和 PyMySQL 实现的 Windows `mysql` 命令。适用于用户希望在 PowerShell/CMD 中输入 `mysql` 时重定向到 Python 实现、需要交互式输入 MySQL 连接信息、需要同步到当前用户本地 bin 目录,或需要将该能力封装成可公开复用的 Codex skill。
- 新建用户推荐用
CREATE USER 'dev'@'192.168.1.%' IDENTIFIED BY 'pwd';+GRANT SELECT ON mydb.* TO 'dev'@'192.168.1.%';,避免手动改表 - 如果已用
UPDATE mysql.user SET Host='%' WHERE User='dev';,必须跟FLUSH PRIVILEGES; - 执行完可立刻验证:
SHOW GRANTS FOR 'dev'@'192.168.1.%';—— 如果返回空,说明权限根本没生效
防火墙、bind_address、认证插件三者常串在一起出问题
哪怕用户和权限都对,只要其中一环卡住,最终也报 Access denied(而不是 Connection refused):
- 先确认 MySQL 监听的是哪个地址:
netstat -tlnp | grep :3306。如果只显示127.0.0.1:3306,说明bind_address = 127.0.0.1没改,远程连不上 - 云服务器务必检查安全组(不只是本地防火墙),阿里云/腾讯云控制台里 3306 入方向规则是否放行目标 IP 段
- MySQL 8.0+ 默认用
caching_sha2_password,老版本 PHP 或 Navicat 可能握手失败,临时切回:ALTER USER 'dev'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd';
真正容易被忽略的是 Host 匹配的精确性——'user'@'%.example.com' 不会匹配 192.168.1.100,'user'@'192.168.1.%' 也不会匹配 IPv6 地址。别猜,查表、试连、看日志(/var/log/mysql/error.log 里常有更细的拒绝原因)。










