REVOKE ALL PRIVILEGES 不影响 USAGE 权限,用户仍可登录但无操作权限;需显式 REVOKE USAGE 才禁止连接,且必须匹配精确 host、检查角色与列级权限,并断开旧连接才能生效。

REVOKE ALL PRIVILEGES 不影响 USAGE 权限
MySQL 中 REVOKE ALL PRIVILEGES 只撤销显式授予的操作类权限(如 SELECT、INSERT),但不会动 USAGE——这是每个账号创建时自动附带的“空权限”,仅允许建立连接,不赋予任何数据库操作能力。所以用户仍能 mysql -u user -p 登录,只是进库后执行任何 DML/DCL 都会报 ERROR 1142 (42000)。
-
USAGE是连接权,不是功能权;它存在于mysql.user表中,且无法被ALL PRIVILEGES覆盖 - 想彻底禁止登录,必须显式执行:
REVOKE USAGE ON *.* FROM 'user'@'host'; - 但注意:
REVOKE USAGE后该账号将完全无法认证,连Access denied都不报,直接拒绝握手 - 生产环境更稳妥的做法是保留
USAGE,靠连接池驱逐 + 应用重启来切断旧会话
已存在连接不会刷新权限快照
MySQL 在连接建立时把用户权限一次性加载进内存,后续所有 REVOKE 操作只修改系统表(如 mysql.db),不触碰已连会话的权限上下文。所以即使你刚执行完 REVOKE ALL PRIVILEGES,当前连接仍可继续 SELECT、USE、甚至 SHOW DATABASES(因默认允许访问 information_schema)。
- 验证是否生效,必须新开连接:
mysql -u user -p -h your_host - GUI 工具(Navicat / DBeaver)常复用连接,删掉连接配置再新建一个才可靠
- 连接池场景下,需主动触发驱逐(如 HikariCP 的
evictConnection())或等空闲超时 -
KILL CONNECTION id可强制断开,但客户端若启用了autoReconnect=true,可能瞬间重建连接
权限范围没对齐导致 REVOKE 实际未生效
MySQL 的 REVOKE 不支持模糊匹配或自动推导。你执行的是 REVOKE ALL PRIVILEGES ON *.* FROM 'user'@'%',但原始授权可能是 'user'@'192.168.1.%' 或 'user'@'localhost'——主机名不一致,命令就等于白跑,还返回 “Query OK”,极具迷惑性。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
- 先查真实授权:
SHOW GRANTS FOR 'user'@'host';,逐字比对ON后面的数据库名、表名、主机名 -
localhost和127.0.0.1是两个不同账号:前者走 Unix socket,后者走 TCP,不能混用 - 确认当前会话身份:
SELECT USER(), CURRENT_USER();,前者是你怎么连的,后者是 MySQL 认你是谁 - 权限语句中的数据库名若含特殊字符(如连字符),必须用反引号包裹:
REVOKE ALL ON `my-db`.* FROM ...
残留权限来自角色或细粒度表
MySQL 8.0+ 支持角色(ROLE),而 REVOKE ALL PRIVILEGES 不解除角色绑定。此外,列级权限存于 mysql.columns_priv,表级单独授权存于 mysql.tables_priv,这些都不会被 ON *.* 覆盖。
- 查角色继承:
SELECT * FROM mysql.role_edges WHERE TO_USER = 'user' AND TO_HOST = 'host'; - 查列级残留:
SELECT * FROM mysql.columns_priv WHERE User = 'user' AND Db = 'target_db'; - 清理角色:
DROP ROLE role_name;或REVOKE role_name FROM 'user'@'host'; - 手动清理系统表前务必备份:
mysqldump mysql columns_priv > backup_columns_priv.sql
真正让权限回收落地的,从来不是那条 REVOKE 命令本身,而是旧连接是否被切断、新连接是否按预期加载了更新后的权限快照。最容易被跳过的动作,是确认 CURRENT_USER() 和检查 mysql.role_edges ——这两步一漏,问题就藏得极深。










