直接改 mysql.user 表会失效,必须用 GRANT 或 ALTER USER
MySQL 8.0+ 默认禁用直接更新
mysql.user表来修改权限,即使你 UPDATE 成功,后续执行
FLUSH PRIVILEGES也可能被忽略或报错。权限变更必须通过 SQL 授权语句生效,否则连接时仍按旧权限校验。
GRANT用于新增或追加权限(如补充
SELECT),但不能撤回已有权限
ALTER USER用于修改密码、账户锁定状态、SSL 要求等属性,不处理对象级权限 真正能「调整」(增删改)权限的组合是:
GRANT+
REVOKE
REVOKE 后必须显式 GRANT,不存在“保留未提及权限”的逻辑
很多人误以为
GRANT SELECT ON db.* TO 'u'@'%'会保留用户已有的
INSERT权限,其实不会。MySQL 的权限模型是“全量覆盖式写入”——
GRANT只设置列出的权限,其他权限不变;但
REVOKE会精准移除指定权限,不影响其余权限。关键点在于:没有“批量保留+局部修改”的快捷语法。 要删掉某个库的
UPDATE但保留
SELECT?用
REVOKE UPDATE ON db.* FROM 'u'@'%'要把用户从所有库权限清空,只留
SELECT到
report.*?先
REVOKE ALL PRIVILEGES ON *.* FROM 'u'@'%',再
GRANT SELECT ON report.* TO 'u'@'%'忘记加
WITH GRANT OPTION?必须先
REVOKE再
GRANT ... WITH GRANT OPTION,不能只补一个词
MySQL 8.0 的角色(ROLE)机制让权限调整更可控
直接给用户授一堆权限容易混乱,尤其多人协作运维时。MySQL 8.0 引入角色后,推荐把权限打包成角色,再把角色赋给用户。这样调整权限只需改角色定义,所有绑定该角色的用户自动同步。
创建角色:CREATE ROLE 'analyst'给角色授权:
GRANT SELECT, SHOW VIEW ON sales.* TO 'analyst'把角色赋予用户:
GRANT 'analyst' TO 'alice'@'%'激活角色(会话级):
SET ROLE 'analyst';设为默认:
SET DEFAULT ROLE 'analyst' TO 'alice'@'%'
之后想禁用某类查询?只需
REVOKE SHOW VIEW ON sales.* FROM 'analyst',无需逐个用户操作。
权限生效延迟常见于 host 匹配或缓存未刷新
执行完
GRANT或
REVOKE后,当前连接不会立即看到新权限——它沿用连接建立时读取的权限快照。新权限只对新建连接生效。但有些情况会让人误判“没生效”: 用户 host 写成
'user'@'192.168.1.%',但客户端实际连的是
192.168.1.100,匹配成功;若连的是
192.168.2.100,则根本找不到该账号,报
Access denied for user使用代理或连接池(如 ProxySQL、HAProxy),可能复用旧连接,需重启代理或等待连接超时 MySQL 8.0+ 中,
FLUSH PRIVILEGES通常不需要,除非你手动改过系统表(不推荐);但某些云数据库控制台操作后,后台可能未触发权限重载
验证权限是否生效,最可靠方式是新开一个连接,然后执行
SHOW GRANTS FOR 'u'@'%'——别信旧终端里的
SELECT结果。
