mysql中GRANT与REVOKE语句的使用与权限管理

来源:这里教程网 时间:2026-02-28 20:45:32 作者:

GRANT 语句怎么写才不会报错 Access denied 或 Illegal GRANT

MySQL 的

GRANT
不是“给权限就完事”,它依赖两个前提:执行者本身有
GRANT OPTION
权限,且目标用户(
'user'@'host'
)在
mysql.user
表中已存在(或能被自动创建)。常见错误包括:

用普通账号执行
GRANT
—— 报错
Access denied; you need (at least one of) the GRANT OPTION privilege(s)
漏写主机名,比如只写
'myuser'
而不是
'myuser'@'localhost'
—— MySQL 会按
'myuser'@'%'
匹配,可能授错对象
对不存在的数据库/表授予权限(如
GRANT SELECT ON nonexistent_db.* TO ...
)—— 语句能执行,但后续访问仍报
Table doesn't exist
,容易误判为权限问题

正确写法示例(以 root 登录后):

GRANT SELECT, INSERT ON `app_db`.* TO 'app_user'@'10.20.%' IDENTIFIED BY 'strong_pass_2024';

注意:

IDENTIFIED BY
在 MySQL 8.0+ 中不推荐用于已有用户(应改用
ALTER USER
),仅首次创建时可用;若用户已存在,去掉该子句。

REVOKE 删除权限后为什么 SHOW GRANTS 还显示旧权限

REVOKE
执行成功不代表权限立即失效,因为 MySQL 权限缓存未刷新。用户当前连接仍保留旧权限,新连接才会生效。更关键的是:如果权限是通过不同 host 条目授予的(比如
'user'@'localhost'
'user'@'127.0.0.1'
),
REVOKE
只影响显式指定的那一行,其余 host 条目不受影响。

执行
REVOKE SELECT ON app_db.* FROM 'app_user'@'10.20.%';
后,立刻查
SHOW GRANTS FOR 'app_user'@'10.20.%';
会更新,但
SHOW GRANTS FOR 'app_user'@'%';
可能还有其它权限
必须手动运行
FLUSH PRIVILEGES;
才能让所有连接感知变更(虽然多数情况下 MySQL 自动重载,但高并发或复制环境建议显式执行)
撤销所有权限的简写是
REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'user'@'host';
,注意它不删除用户,只清空权限

MySQL 8.0 权限模型变化:ROLE 与 WITH GRANT OPTION 的区别

MySQL 8.0 引入角色(

CREATE ROLE
),但角色权限和直接授权行为不等价。核心差异在于:
WITH GRANT OPTION
允许被授权者再转授,而角色不能直接转授(需显式
GRANT ROLE ... TO ... WITH ADMIN OPTION
)。

老写法:
GRANT SELECT ON sales.* TO 'analyst'@'%' WITH GRANT OPTION;
→ analyst 可再执行
GRANT SELECT ON sales.* TO 'intern'@'%';
角色写法:
CREATE ROLE 'sales_reader'; GRANT SELECT ON sales.* TO 'sales_reader'; GRANT 'sales_reader' TO 'analyst'@'%';
→ analyst 默认无法把
sales_reader
授给别人,除非加
WITH ADMIN OPTION
权限继承是静态的:用户被授予角色后,角色权限变更会自动同步;但若用户已有直接权限,角色权限不会覆盖它

所以不要以为建了 role 就一劳永逸——

SHOW GRANTS
会同时列出直接权限和角色权限,排查时得两头看。

最小权限原则落地:哪些权限其实不该轻易给

生产环境最常被过度授予、又最容易引发事故的权限有三个:

FILE
PROCESS
SUPER
。它们不属于数据库对象操作,而是服务器级控制权。

FILE
:允许用户读写服务器任意文件(
LOAD DATA INFILE
/
SELECT ... INTO OUTFILE
),一旦 Web 应用存在 SQL 注入,攻击者可直接读取
/etc/passwd
或写入 Webshell
PROCESS
:能看到所有连接的完整 SQL(含密码明文),
SHOW PROCESSLIST
输出敏感信息
SUPER
:可 kill 任意线程、修改全局变量(如关掉
sql_log_bin
绕过 binlog)、甚至切换主从复制状态 —— 运维账号才应持有

真正业务账号,通常只需:

SELECT
INSERT
UPDATE
DELETE
(按需限制库/表),外加
EXECUTE
(调用存储过程)和
SHOW VIEW
(查视图)。连
CREATE
都该由 DBA 统一管理。

相关推荐