在 MySQL 中,权限管理是数据库安全的核心组成部分。MySQL 提供了一套完整的 数据控制语言(DCL, Data Control Language) 用于用户账户的创建、授权、权限查询、撤销和删除。
这些操作主要通过数据库 mysql 中的权限表(如 user、db、tables_priv 等)进行控制,并可通过 SQL 语句或管理命令实现。
一、权限相关 SQL 分类总览
| 类别 | SQL 语句 | 功能 |
|---|---|---|
| 用户管理 | CREATE USER ALTER USER DROP USER |
创建、修改、删除用户 |
| 权限授予 | GRANT |
授予用户或角色权限 |
| 权限撤销 | REVOKE |
撤销用户或角色权限 |
| 权限查询 | SHOW GRANTS |
查看用户或角色的权限 |
| 角色管理(MySQL 8.0+) | CREATE ROLE DROP ROLE GRANT role TO user REVOKE role FROM user SET DEFAULT ROLE SET ROLE |
角色的创建、分配、激活等 |
| 密码与安全策略 | SET PASSWORD ALTER USER ... IDENTIFIED BY |
修改密码、设置过期策略等 |
✅ 所有 DCL 语句在执行后自动刷新权限缓存 ,无需手动
FLUSH PRIVILEGES(除非直接修改mysql系统表)。
二、详细语法与说明
1. 用户管理
(1) CREATE USER
创建新用户账户。
sql
CREATE USER 'username'@'host'
IDENTIFIED BY 'password'
[REQUIRE {NONE | SSL | X509 | ...}]
[PASSWORD EXPIRE [DEFAULT | NEVER | INTERVAL N DAY]]
[ACCOUNT LOCK | UNLOCK];
示例:
sql
CREATE USER 'app_user'@'192.168.1.%' IDENTIFIED BY 'SecurePass123!';
CREATE USER 'temp'@'localhost' PASSWORD EXPIRE INTERVAL 30 DAY;
(2) ALTER USER
修改现有用户属性(密码、过期策略、锁定状态等)。
sql
ALTER USER 'username'@'host'
IDENTIFIED BY 'new_password'
[PASSWORD EXPIRE | NEVER]
[ACCOUNT LOCK | UNLOCK];
示例:
sql
ALTER USER 'old_user'@'%' IDENTIFIED BY 'NewPass456' PASSWORD EXPIRE;
ALTER USER 'test'@'localhost' ACCOUNT LOCK;
(3) DROP USER
删除用户账户会同时移除该用户的所有权限(包括全局、数据库、表等各级权限),并从 mysql.user 及其他权限表中清除记录。
sql
DROP USER [IF EXISTS] 'username'@'host' [, 'user2'@'host2'] ...;
示例:
sql
-- 删除单个用户
DROP USER 'temp_user'@'localhost';
-- 删除多个用户
DROP USER 'user1'@'%', 'user2'@'192.168.%';
2. 权限授予:GRANT
语法
sql
GRANT privilege_type [(column_list)]
ON [database_name.][table_name]
TO 'username'@'host' [, 'user2'@'host2'] ...
[WITH GRANT OPTION]
[AS role_name]; -- MySQL 8.0+
常见权限类型
| 权限 | 作用范围 | 说明 |
|---|---|---|
ALL [PRIVILEGES] |
全局/数据库/表 | 所有可用权限(不含 GRANT OPTION) |
SELECT, INSERT, UPDATE, DELETE |
表/列 | DML 操作 |
CREATE, DROP, ALTER |
数据库/表 | DDL 操作 |
USAGE |
全局 | "无权限",仅允许连接 |
GRANT OPTION |
全局/数据库/表 | 允许将自身权限授予他人 |
PROCESS, RELOAD, SHUTDOWN |
全局 | 管理权限(高危!) |
示例
sql
-- 授予数据库级读写权限
GRANT SELECT, INSERT, UPDATE ON mydb.* TO 'app_user'@'%';
-- 授予全局只读(监控账号)
GRANT SELECT ON *.* TO 'monitor'@'10.0.0.%';
-- 授予列级权限
GRANT SELECT (id, name), UPDATE (email) ON mydb.users TO 'hr_user'@'localhost';
-- 允许转授权限
GRANT SELECT ON mydb.* TO 'delegate'@'%' WITH GRANT OPTION;
3. 权限撤销:REVOKE
语法
sql
REVOKE privilege_type [(column_list)]
ON [database_name.][table_name]
FROM 'username'@'host' [, ...];
-- 撤销所有权限(包括 GRANT OPTION)
REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'user'@'host';
-- 撤销数据库级权限
REVOKE INSERT, UPDATE ON mydb.* FROM 'app_user'@'%';
-- 撤销全局权限
REVOKE CREATE USER ON *.* FROM 'admin'@'localhost';
示例
sql
REVOKE UPDATE ON mydb.orders FROM 'app_user'@'%';
REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'temp_user'@'localhost';
注意:
REVOKE不会删除用户,仅移除权限。
4. 查看权限:SHOW GRANTS
语法
sql
SHOW GRANTS; -- 当前用户
SHOW GRANTS FOR 'username'@'host'; -- 指定用户
SHOW GRANTS FOR CURRENT_USER(); -- 显式当前用户
输出示例:
sql
GRANT USAGE ON *.* TO `app_user`@`%`
GRANT SELECT, INSERT ON `mydb`.* TO `app_user`@`%`
✅ 返回的是可直接执行的
GRANT语句,便于权限迁移或审计。
直接查询权限表
sql
-- 全局权限
SELECT * FROM mysql.user WHERE User = 'username' AND Host = 'host';
-- 数据库级权限
SELECT * FROM mysql.db WHERE User = 'username' AND Host = 'host';
-- 表级权限
SELECT * FROM mysql.tables_priv WHERE User = 'username' AND Host = 'host';
5. 角色管理(MySQL 8.0+)
角色是一组权限的集合,可简化权限分配。
(1) 创建/删除角色
sql
CREATE ROLE 'role_name';
DROP ROLE 'role_name';
(2) 授予角色权限
sql
GRANT SELECT, INSERT ON mydb.* TO 'data_reader';
(3) 将角色授予用户
sql
GRANT 'data_reader' TO 'app_user'@'%';
(4) 激活角色
sql
-- 默认不激活,需设置默认角色
SET DEFAULT ROLE 'data_reader' TO 'app_user'@'%';
-- 或会话中临时激活
SET ROLE 'data_reader';
SET ROLE ALL; -- 激活所有授予的角色
SET ROLE NONE; -- 停用所有角色
(5) 查看角色权限
sql
SHOW GRANTS FOR 'app_user'@'%'; -- 显示角色分配
SHOW GRANTS FOR 'app_user'@'%' USING 'data_reader'; -- 显示角色展开后的权限
6. 密码管理
(1) 修改密码(多种方式)
sql
-- 方式1:SET PASSWORD(推荐)
SET PASSWORD FOR 'user'@'host' = 'new_password';
-- 方式2:ALTER USER(更灵活)
ALTER USER 'user'@'host' IDENTIFIED BY 'new_password';
-- 方式3:旧版(不推荐)
SET PASSWORD = PASSWORD('new_password'); -- 仅当前用户,且明文风险
(2) 强制密码过期
sql
ALTER USER 'user'@'host' PASSWORD EXPIRE;
7. 查看用户
(1) 查看所有用户
sql
SELECT User, Host FROM mysql.user;
⚠️ 注意:执行此语句需要具有 SELECT 权限访问 mysql.user 表(通常为管理员权限)
(2) 查看当前登录用户
sql
SELECT USER(), CURRENT_USER();
USER():客户端尝试连接时使用的用户名和主机。CURRENT_USER():实际被认证的账户(用于权限判断)。
三、权限层级与作用范围
| 层级 | 语法形式 | 存储表 |
|---|---|---|
| 全局 | ON *.* |
mysql.user |
| 数据库 | ON db_name.* |
mysql.db |
| 表 | ON db_name.tbl_name |
mysql.tables_priv |
| 列 | ON db_name.tbl_name (col1, col2) |
mysql.columns_priv |
| 存储过程/函数 | ON PROCEDURE db_name.proc_name |
mysql.procs_priv |
权限检查顺序:全局 → 数据库 → 表 → 列(取最具体的匹配)。
四、常用权限审计与清理命令汇总
sql
-- 1. 列出所有用户
SELECT User, Host FROM mysql.user;
-- 2. 查看某用户权限
SHOW GRANTS FOR 'user'@'host';
-- 3. 查找空密码用户
SELECT User, Host FROM mysql.user WHERE authentication_string = '';
-- 4. 查找通配符主机高权限用户
SELECT User, Host FROM mysql.user
WHERE Host = '%' AND (Insert_priv = 'Y' OR Super_priv = 'Y');
-- 5. 撤销所有权限并删除用户
REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'user'@'host';
DROP USER 'user'@'host';
-- 6. 刷新权限(仅在直接修改 mysql 表时需要)
FLUSH PRIVILEGES;
五、重要注意事项
-
权限由
(User, Host)唯一确定
'admin'@'localhost'≠'admin'@'%'。 -
GRANT自动创建用户(若不存在)sqlGRANT SELECT ON *.* TO 'newuser'@'%' IDENTIFIED BY 'pass'; -- 不推荐!⚠️ 此行为在 MySQL 8.0 中已被弃用 ,建议先
CREATE USER再GRANT。 -
USAGE权限 = 无权限,仅允许连接常用于限制用户只能登录但不能操作数据。
-
不要直接修改
mysql系统表应使用 DCL 语句,否则需手动
FLUSH PRIVILEGES。 -
权限变更对新连接生效
已存在的连接仍保留旧权限,直到重连。
六、权限生效机制
- MySQL 在启动时或执行
FLUSH PRIVILEGES时加载权限表到内存。 - 使用
GRANT、REVOKE、CREATE USER、DROP USER等语句会自动更新内存中的权限缓存,无需手动刷新。 - 直接修改
mysql库中的表(如UPDATE mysql.user)不会立即生效 ,必须执行FLUSH PRIVILEGES;。
七、总结:权限管理最佳实践
- 先
CREATE USER,再GRANT; - 使用最小权限原则;
- 避免
'user'@'%',限制具体 IP 或子网; - 定期审计:
SHOW GRANTS+ 连接日志分析; - MySQL 8.0+ 优先使用 角色(Role) 管理复杂权限;
- 敏感操作记录到审计日志。