[小技巧19]MySQL 权限管理全指南:用户、角色、授权与安全实践

在 MySQL 中,权限管理是数据库安全的核心组成部分。MySQL 提供了一套完整的 数据控制语言(DCL, Data Control Language) 用于用户账户的创建、授权、权限查询、撤销和删除。

这些操作主要通过数据库 mysql 中的权限表(如 userdbtables_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;

五、重要注意事项

  1. 权限由 (User, Host) 唯一确定
    'admin'@'localhost''admin'@'%'

  2. GRANT 自动创建用户(若不存在)

    sql 复制代码
    GRANT SELECT ON *.* TO 'newuser'@'%' IDENTIFIED BY 'pass'; -- 不推荐!

    ⚠️ 此行为在 MySQL 8.0 中已被弃用 ,建议先 CREATE USERGRANT

  3. USAGE 权限 = 无权限,仅允许连接

    常用于限制用户只能登录但不能操作数据。

  4. 不要直接修改 mysql 系统表

    应使用 DCL 语句,否则需手动 FLUSH PRIVILEGES

  5. 权限变更对新连接生效

    已存在的连接仍保留旧权限,直到重连。

六、权限生效机制

  • MySQL 在启动时或执行 FLUSH PRIVILEGES 时加载权限表到内存。
  • 使用 GRANTREVOKECREATE USERDROP USER 等语句会自动更新内存中的权限缓存,无需手动刷新。
  • 直接修改 mysql 库中的表(如 UPDATE mysql.user不会立即生效 ,必须执行 FLUSH PRIVILEGES;

七、总结:权限管理最佳实践

  • CREATE USER,再 GRANT
  • 使用最小权限原则;
  • 避免 'user'@'%',限制具体 IP 或子网;
  • 定期审计:SHOW GRANTS + 连接日志分析;
  • MySQL 8.0+ 优先使用 角色(Role) 管理复杂权限;
  • 敏感操作记录到审计日志。
相关推荐
jiayou645 小时前
KingbaseES 实战:深度解析数据库对象访问权限管理
数据库
于眠牧北6 小时前
MySQL的锁类型,表锁,行锁,MVCC中所使用的临键锁
mysql
李广坤1 天前
MySQL 大表字段变更实践(改名 + 改类型 + 改长度)
数据库
Turnip12022 天前
深度解析:为什么简单的数据库"写操作"会在 MySQL 中卡住?
后端·mysql
爱可生开源社区2 天前
2026 年,优秀的 DBA 需要具备哪些素质?
数据库·人工智能·dba
随逸1772 天前
《从零搭建NestJS项目》
数据库·typescript
一次旅行3 天前
网络安全总结
安全·web安全
加号33 天前
windows系统下mysql多源数据库同步部署
数据库·windows·mysql
シ風箏3 天前
MySQL【部署 04】Docker部署 MySQL8.0.32 版本(网盘镜像及启动命令分享)
数据库·mysql·docker
李慕婉学姐3 天前
Springboot智慧社区系统设计与开发6n99s526(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端