第一件事是执行select user(), current_user()确认实际认证身份,因user()显示声称账号而current_user()才是mysql匹配成功的(user,host);两者不一致说明host匹配失败,如'localhost'与'127.0.0.1'为不同账号、dns解析问题或空格大小写错误。

SELECT USER(), CURRENT_USER() 立刻查身份
执行 GRANT 后权限不生效,第一件事不是重试授权,而是确认你连的到底是谁。USER() 返回你“声称”的账号(比如 'u'@'%'),CURRENT_USER() 才是 MySQL 实际认证成功的账号(比如 'u'@'192.168.1.100')。两者不一致,说明 host 匹配失败——常见于:'u'@'localhost' 和 'u'@'127.0.0.1' 是两个独立账号;DNS 解析开启时 'u'@'%' 可能匹配不到具体 IP;多一个空格或大小写不一致也会导致匹配失败。
权限粒度决定是否需要重连
MySQL 不是统一刷新所有权限,不同粒度生效时机完全不同:
- 表级权限(如
GRANT SELECT ON db.t TO 'u'@'h'):下次查询该表即生效,当前连接内可直接用 - 库级权限(如
GRANT SELECT ON db.* TO 'u'@'h'):必须先执行USE db才触发加载,不用重连 - 全局权限(如
GRANT DROP ON *.* TO 'u'@'h'):只对新连接生效,当前会话无论怎么USE都无效,必须QUIT后重连
MySQL 8.0+ 角色和认证插件必须手动激活
在 8.0+ 版本中,GRANT 'role_name' TO 'u'@'h' 只建立绑定,不启用权限。必须额外执行:SET DEFAULT ROLE 'role_name' TO 'u'@'h',否则登录后 CURRENT_USER() 对应的角色权限完全不可见。同时注意认证插件兼容性:caching_sha2_password 是默认插件,但老客户端(如旧版 JDBC、Navicat)可能静默降级失败,表现为“能连上,一查就断”,临时解法是:ALTER USER 'u'@'h' IDENTIFIED WITH mysql_native_password BY 'pwd'。
免费 DNS 与邮件安全分析(IntoDNS.ai):包括 DNSSEC、SPF、DKIM、DMARC、MTA-STS、BIMI、SMTP STARTTLS、FCrDNS、黑名单、发件人要求及报告。
别信 SHOW GRANTS,直接跑 SQL 验证
SHOW GRANTS FOR 'u'@'h' 只说明授权语句执行成功,不代表当前连接可用。真正验证方式是实操:
- 如果是表级权限,直接
SELECT * FROM t LIMIT 1 - 如果是库级权限,先
USE db,再查任意表 - 如果是全局权限,退出后重新用完全相同的参数连接(注意 host 是否一致)
- 检查账户是否被锁:
SELECT User, Host, account_locked FROM mysql.user WHERE User = 'u'
最容易被忽略的是:你改的是 Docker 容器里的 MySQL,却从宿主机用 mysql -u u -p 连到了系统自带实例;或者 bind-address = 127.0.0.1 导致远程连接根本进不来——权限再全也没用。










