select user()和current_user()不一致说明认证账号不匹配,权限只对current_user()对应的记录生效;必须据此精确授权并重新连接,旧会话权限不会更新。

SELECT USER() 和 CURRENT_USER() 不一致导致权限不生效
执行 GRANT 成功不代表当前连接会立刻获得新权限——MySQL 在连接建立时就锁定了认证身份,后续权限变更对已存在的连接完全无效。最典型的表现是:你用 mysql -h 192.168.1.100 -u user -p 登录,但授权写的是 'user'@'%',而 MySQL 实际匹配到的是 'user'@'192.168.1.100'(IP 字面量),不是 %;或者你本机连却用了 127.0.0.1(走 TCP),但只授权了 'user'@'localhost'(走 socket),两者在权限表里是完全独立的账号。
必须查清真实认证账号:SELECT USER(), CURRENT_USER();
前者是你“声称”的身份,后者才是 MySQL 实际用来查权限的账号。只有 CURRENT_USER() 对应的那条记录里的权限才生效。
- 如果
CURRENT_USER()返回'user'@'192.168.1.100',就得单独给这个 host 授权,不能只靠'user'@'%' - 如果返回
'user'@'localhost',但你是用127.0.0.1连的,说明 DNS 解析失败且skip_name_resolve=OFF,此时要改 host 或开skip_name_resolve - 改完权限后,必须退出重连——
EXIT;再重新mysql -u user -p -h ...,旧连接不会更新权限上下文
bind-address 仍为 127.0.0.1 导致远程连接根本进不来
哪怕 GRANT ALL ON *.* TO 'user'@'%' 执行得再漂亮,只要 MySQL 只监听 127.0.0.1,所有远程 TCP 包都会被操作系统直接丢弃,压根到不了 MySQL 的权限校验层。
检查配置:
Linux/macOS 查 /etc/mysql/mysql.conf.d/mysqld.cnf 或 /etc/my.cnf 中 [mysqld] 段的 bind-address;Windows 查 C:\ProgramData\MySQL\MySQL Server X.X\my.ini。
它不能是 127.0.0.1,必须注释掉或改为 0.0.0.0。
- 改完必须重启服务:
sudo systemctl restart mysql(Linux)或net stop mysql && net start mysql(Windows) - 验证是否生效:
ss -tln | grep :3306,输出里要有*:3306或0.0.0.0:3306,不能只有127.0.0.1:3306 - 云服务器还要确认安全组放行 3306 入方向——光开系统防火墙(如 ufw)不够
MySQL 8.0+ 的 caching_sha2_password 插件让旧客户端静默失败
能输入密码、看到欢迎信息,但一执行 SHOW DATABASES 就断开或报 Access denied,大概率不是权限问题,而是握手阶段认证失败。MySQL 8.0 默认用 caching_sha2_password,但很多老客户端不支持:
- PHP 7.4 以下、Navicat 12 以下、JDBC 驱动 8.0 以前版本
- 表现是连接建立后立刻中断,日志里可能没有明显错误,容易误判为权限未生效
- 查真实插件:
SELECT User, Host, plugin FROM mysql.user WHERE User = 'user'; - 临时修复(仅限该用户):
ALTER USER 'user'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd';
不建议全局改默认插件,会影响所有新建用户。
SHOW DATABASES 只见系统库,其实是权限粒度太细
执行 GRANT SELECT ON mydb.* TO 'user'@'%' 后登录,SHOW DATABASES 却只显示 information_schema 和 performance_schema,不是权限没给,而是权限没覆盖到“列出数据库”这个动作本身。
MySQL 的 SHOW DATABASES 行为受两层控制:
- 有
SELECT权限的数据库才会出现在列表里(所以只给了mydb.*,就只显示mydb) - 连
mysql库都没有SELECT权限的话,连mysql都不会显示——而某些客户端初始化时会尝试读mysql.db,失败就静默降级 - 想看到所有库,要么给
SELECT ON *.*,要么至少给SELECT ON mysql.*(注意:不是mysql数据库的访问权,而是让它出现在列表里)
真正麻烦的是那些隐式依赖:比如旧版 DBeaver 初始化连接时会尝试 CREATE TEMPORARY TABLES,如果没显式授予,且 sql_mode=STRICT_TRANS_TABLES 开启,就会静默失败——现象和权限无关,但根源就在权限漏项。











