mysql用户权限管理与权限授予语法

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

GRANT 语句的基本写法和权限粒度

MySQL 的权限控制是分层的,

GRANT
不是“给用户赋一个权限”那么简单,而是必须明确「作用对象」+「权限类型」+「生效范围」。漏掉任何一项都可能授错权,或根本不起作用。

常见错误是只写

GRANT SELECT ON *.*
却没指定用户和主机,结果命令执行成功但权限没落到目标账户上。

权限类型要精确:比如
SELECT
INSERT
UPDATE
是表级;
CREATE
DROP
是数据库级;
RELOAD
SHUTDOWN
是全局管理权限
作用对象格式为
db_name.tbl_name
*
表示所有库,
*.*
表示所有库所有表,
`mydb`.*
表示 mydb 库下所有表(注意反引号用于转义含特殊字符的库名)
用户标识必须带主机:如
'appuser'@'192.168.1.%'
'admin'@'localhost'
,不写主机名默认是
'user'@'%'
,但新版本 MySQL 8.0+ 默认禁用
%
匹配本地连接

MySQL 8.0+ 与旧版本在权限语法上的关键差异

MySQL 8.0 彻底重构了权限系统,最大的变化是把以前隐式包含的权限(如

USAGE
)显式化,并废弃了部分旧语法。直接沿用 5.7 的脚本在 8.0 上会报错。

典型报错:

ERROR 1410 (42000): You are not allowed to create a user with GRANT
—— 这是因为 8.0 默认关闭了
create_user_priv
自动授予,且要求先
CREATE USER
GRANT

必须先显式创建用户:
CREATE USER 'dev'@'%' IDENTIFIED BY 'p@ssw0rd';
再授权:
GRANT SELECT, INSERT ON `testdb`.* TO 'dev'@'%';
刷新权限仍需:
FLUSH PRIVILEGES;
,但仅在手动修改
mysql.user
表后才真正必要;用
GRANT
命令操作后权限立即生效
WITH GRANT OPTION
依然可用,但授予该权限的用户不能跨主机代理(例如
'a'@'%' WITH GRANT OPTION
无法给
'b'@'10.0.0.5'
授权)

常见误授场景:哪些权限看起来安全实则危险

开发常以为只给

SELECT
就够安全,但忽略元数据访问和执行上下文风险。有些权限表面普通,组合使用却可导致信息泄露甚至提权。

SHOW DATABASES
:默认关闭,但一旦开启,用户能看到所有库名,可能暴露测试/备份库路径
FILE
权限:允许读写服务器文件系统(如
SELECT ... INTO OUTFILE
LOAD DATA INFILE
),配合
SELECT
可能读取
/etc/passwd
或 MySQL 配置文件
PROCESS
:能看到其他用户正在执行的 SQL,含敏感条件或临时表名
EXECUTE
:如果数据库里有定义好的存储过程,且该过程内含
INSERT/UPDATE
,那么仅授
EXECUTE
就等价于间接授了写权限

验证权限是否生效的可靠方式

别只信

SHOW GRANTS FOR 'u'@'h';
的输出,它只显示「被授予的语句」,不反映最终生效权限(比如被
REVOKE
后未刷缓存,或角色权限未激活)。最准的方式是切到该用户连接后实测。

用目标用户登录:
mysql -u dev -p -h db.example.com
检查当前有效权限:
SELECT * FROM INFORMATION_SCHEMA.ROLE_TABLE_GRANTS WHERE GRANTEE = "'dev'@'%'" \G
(8.0+ 角色场景)或更通用的
SHOW GRANTS;
直接尝试敏感操作,例如:
DROP TABLE IF EXISTS test; -- 看是否报 ERROR 1142
注意:权限检查是逐层匹配的,MySQL 优先匹配最具体的规则(如
'u'@'192.168.1.100'
'u'@'%'
优先),所以主机名精度比用户名更重要

权限系统里最易被忽略的是「撤销后残留」——

REVOKE
不会自动清除用户账号,也不会影响已建立的活跃连接。连接保持期间旧权限仍然有效,直到断开重连。

相关推荐