乐途乐途
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
  • 学习路径
  • 第1章 数据库基础与安装

    • MySQL 简介
    • MySQL 5.6 到 5.7 到 8.0 关键差异速查
    • 安装 MySQL 5.7
    • 连接与断开服务器
    • 创建数据库
    • 创建数据表
    • 数据库与数据表
    • 加载数据
    • 获取数据库信息
    • 批处理模式
    • SHOW 语句汇总
    • FLUSH 与 RESET 语句
    • my.cnf 核心参数
    • 字符集与排序规则
  • 第2章 SQL基础查询

    • SELECT
    • WHERE
    • ORDER BY
    • LIMIT
    • COUNT
    • 聚合函数
    • 比较运算符
    • 逻辑运算符
    • 算术运算符
    • 模式匹配
    • NULL 值处理
    • UPDATE
    • DELETE
    • REPLACE
    • SELECT INTO
  • 第3章 数据类型与运算符

    • 数值类型
    • 字符串类型
    • 日期时间类型
    • BIT 类型
    • ENUM 类型
    • SET 类型
    • JSON 类型
    • 类型转换
  • 第4章 函数与表达式

    • 字符串函数
    • 数值函数
    • 日期函数
    • 全文检索函数
  • 第5章 高级查询与子查询

    • JOIN
    • 子查询
    • UNION
    • GROUP BY
    • HAVING
    • DISTINCT
  • 第6章 表与索引

    • 数据定义语言
    • 修改表结构
    • 视图
    • 修改视图与检查选项
    • 外键
    • 索引
    • 唯一索引
    • 复合索引
    • 存储引擎对比
    • 分区表
    • 第一范式与第二范式
    • 第三范式与 BC 范式
    • 反范式设计
  • 第7章 存储过程与函数

    • 存储过程
    • 存储函数
    • 变量
    • 流程控制
    • 游标
    • 预处理语句
  • 第8章 事务与锁

    • 事务
    • 事务隔离级别
    • 锁机制
    • MVCC
    • 死锁专题分析
    • LOCK TABLES
    • XA 事务
  • 第9章 用户管理与安全

    • 用户管理
    • 权限管理
    • 角色
    • SQL 注入防范
  • 第10章 性能优化入门

    • 执行计划
    • 索引优化
    • 查询优化
    • 查询优化器提示
    • 慢查询日志
    • InnoDB 深入机制
    • InnoDB 专项优化
    • Performance Schema
    • sys Schema
  • 第11章 复制与高可用

    • 主从复制原理
    • 半同步复制配置
    • binlog 开启与 point-in-time 恢复
    • mysqldump 全库备份
    • mysqldump 单表与条件备份
    • mysqldump 恢复与导入
    • xtrabackup 全量热备
    • xtrabackup 准备与恢复
    • xtrabackup 增量与流式备份
  • 第12章 触发器与事件

    • 触发器
    • 事件调度器
  • 参考

    • MySQL 5.7 专业术语大全
    • MySQL 5.7 关键字与保留字大全

权限管理

导学

创建用户后,必须精确控制他们能做什么。MySQL 的权限系统粒度从全局到列级,理解权限层级和 GRANT 语法是数据库安全的核心。

定义

权限(Privilege):允许用户执行的特定操作。MySQL 权限按作用范围分为全局级、数据库级、表级、列级和存储过程级。

核心权限类型

权限作用范围说明
ALL PRIVILEGES所有所有权限(除 GRANT OPTION)
SELECT表/列查询数据
INSERT表/列插入数据
UPDATE表/列更新数据
DELETE表删除数据
CREATE数据库/表创建对象
DROP数据库/表删除对象
ALTER表修改表结构
INDEX表创建/删除索引
EXECUTE存储过程执行存储过程/函数
GRANT OPTION所有允许将权限授予他人
SUPER全局管理操作(改全局变量、杀线程等)
REPLICATION SLAVE全局复制从库权限

GRANT 语法

GRANT 权限列表 ON 作用范围 TO '用户'@'主机' [WITH GRANT OPTION];
作用范围含义示例
*.*所有数据库的所有对象GRANT SELECT ON *.*
db_name.*指定数据库的所有对象GRANT ALL ON app_db.*
db_name.table_name指定表GRANT SELECT ON app_db.employees
db_name.table_name(col)指定列GRANT UPDATE(dept) ON app_db.employees

SQL 示例

前置准备:建立测试环境

-- 创建测试数据库
CREATE DATABASE IF NOT EXISTS app_db CHARACTER SET utf8mb4;
USE app_db;

-- 创建员工表
CREATE TABLE employees (
    emp_id INT AUTO_INCREMENT PRIMARY KEY,
    emp_name VARCHAR(20),
    dept VARCHAR(20),
    score DECIMAL(5, 2)
);

-- 插入测试数据
INSERT INTO employees (emp_name, dept, score) VALUES
('大翔', '技术部', 100),
('白歌', '技术部', NULL);

当前数据状态(employees 表):

emp_idemp_namedeptscore
1大翔技术部100
2白歌技术部NULL

场景一:授予全局级权限

第一步:创建测试用户

CREATE USER 'global_reader'@'localhost'
IDENTIFIED BY 'GlobalReader123!';

第二步:授权前验证

以 'global_reader'@'localhost' 连接数据库:

USE app_db;
SELECT * FROM employees;

结果:

ERROR 1142 (42000): SELECT command denied to user 'global_reader'@'localhost' for table 'employees'

第三步:授予全局 SELECT 权限

GRANT SELECT ON *.* TO 'global_reader'@'localhost';

第四步:查看授权结果

SHOW GRANTS FOR 'global_reader'@'localhost';

操作后的权限状态:

Grants for global_reader@localhost
GRANT SELECT ON . TO 'global_reader'@'localhost'

第五步:授权后验证

以 'global_reader'@'localhost' 连接数据库:

USE app_db;
SELECT * FROM employees;

验证结果:

emp_idemp_namedeptscore
1大翔技术部100
2白歌技术部NULL
-- 尝试 INSERT(应该失败,未授予)
INSERT INTO employees (emp_name) VALUES ('测试');

结果:

ERROR 1142 (42000): INSERT command denied to user 'global_reader'@'localhost' for table 'employees'

结果解读:

  • SELECT ON *.* 授予了该用户对所有数据库、所有表的查询权限。
  • 全局级权限存储在 mysql.user 表中,影响范围最广,应谨慎授予。
  • 该用户只能查询,不能执行 INSERT、UPDATE、DELETE 等修改操作。

第六步:回收权限

REVOKE SELECT ON *.* FROM 'global_reader'@'localhost';

SHOW GRANTS FOR 'global_reader'@'localhost';

回收后的权限状态:

Grants for global_reader@localhost
GRANT USAGE ON . TO 'global_reader'@'localhost'

第七步:清理

DROP USER 'global_reader'@'localhost';

场景二:授予数据库级权限

第一步:创建测试用户

CREATE USER 'db_admin'@'localhost'
IDENTIFIED BY 'DbAdmin123!';

第二步:授权前验证

以 'db_admin'@'localhost' 连接数据库:

USE app_db;
SHOW TABLES;

结果:

ERROR 1044 (42000): Access denied for user 'db_admin'@'localhost' to database 'app_db'

第三步:授予数据库级所有权限

GRANT ALL PRIVILEGES ON app_db.* TO 'db_admin'@'localhost';

第四步:查看授权结果

SHOW GRANTS FOR 'db_admin'@'localhost';

操作后的权限状态:

Grants for db_admin@localhost
GRANT USAGE ON . TO 'db_admin'@'localhost'
GRANT ALL PRIVILEGES ON app_db.* TO 'db_admin'@'localhost'

第五步:授权后验证

以 'db_admin'@'localhost' 连接数据库:

USE app_db;

-- 查询(成功)
SELECT * FROM scores;

验证结果:

score_idemp_idscore
1190
2285
-- 插入(成功)
INSERT INTO scores (emp_id, score) VALUES (1, 88);

-- 更新(成功)
UPDATE scores SET score = 88 WHERE score_id = 2;

-- 删除(成功)
DELETE FROM scores WHERE score_id = 2;

-- 创建新表(成功)
CREATE TABLE logs (
    log_id INT PRIMARY KEY AUTO_INCREMENT,
    emp_id INT,
    action VARCHAR(20),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 尝试访问其他数据库(失败)
USE mysql;
SELECT * FROM mysql.user;

结果:

ERROR 1142 (42000): SELECT command denied to user 'db_admin'@'localhost' for table 'user'

操作后的数据状态(scores 表):

score_idemp_idscore
1190
2288

操作后的数据状态(logs 表已创建):

SHOW TABLES;
Tables_in_app_db
employees
logs
scores

结果解读:

  • ALL PRIVILEGES ON app_db.* 授予了对 app_db 数据库中所有对象的全部操作权限(除 GRANT OPTION)。
  • 该用户可以在 app_db 库内自由查询、修改、删除、创建表,但无法访问 mysql 系统库或其他数据库。
  • 数据库级权限存储在 mysql.db 表中。

第六步:回收部分权限

-- 回收 DELETE 权限
REVOKE DELETE ON app_db.* FROM 'db_admin'@'localhost';

SHOW GRANTS FOR 'db_admin'@'localhost';

回收后的权限状态:

Grants for db_admin@localhost
GRANT USAGE ON . TO 'db_admin'@'localhost'
GRANT SELECT, INSERT, UPDATE, CREATE, DROP, ... ON app_db.* ...

注意:REVOKE DELETE 后,权限列表中不再包含 DELETE,但仍保留 SELECT、INSERT、UPDATE、CREATE、DROP 等。

第七步:验证回收后的权限

以 'db_admin'@'localhost' 连接数据库:

USE app_db;

-- 尝试 DELETE(失败)
DELETE FROM scores WHERE score_id = 1;

结果:

ERROR 1142 (42000): DELETE command denied to user 'db_admin'@'localhost' for table 'scores'
-- SELECT 仍然可以执行(成功)
SELECT * FROM scores;

结果:

score_idemp_idscore
1190
2288

第八步:清理

REVOKE ALL PRIVILEGES ON app_db.* FROM 'db_admin'@'localhost';
DROP USER 'db_admin'@'localhost';

场景三:授予表级权限

第一步:创建测试用户

CREATE USER 'table_user'@'localhost'
IDENTIFIED BY 'TableUser123!';

第二步:授予精确到表的权限

-- 只能读 employees 表
GRANT SELECT ON app_db.employees TO 'table_user'@'localhost';

-- 可以读写 scores 表,但不能删表
GRANT SELECT, INSERT, UPDATE, DELETE ON app_db.scores TO 'table_user'@'localhost';

第三步:查看授权结果

SHOW GRANTS FOR 'table_user'@'localhost';

操作后的权限状态:

Grants for table_user@localhost
GRANT USAGE ON . TO 'table_user'@'localhost'
GRANT SELECT ON app_db.employees TO 'table_user'@'localhost'
GRANT SELECT, INSERT, UPDATE, DELETE ON app_db.scores TO 'table_user'@'localhost'

第四步:验证权限边界

以 'table_user'@'localhost' 连接数据库:

USE app_db;

-- employees 表:只能 SELECT(成功)
SELECT * FROM employees;

验证结果:

emp_idemp_namedeptscore
1大翔技术部100
2白歌技术部NULL
-- employees 表:尝试 INSERT(失败)
INSERT INTO employees (emp_name) VALUES ('测试');

结果:

ERROR 1142 (42000): INSERT command denied to user 'table_user'@'localhost' for table 'employees'
-- scores 表:可以 INSERT(成功)
INSERT INTO scores (emp_id, score) VALUES (1, 88);

-- scores 表:可以 DELETE(成功)
DELETE FROM scores WHERE score_id = 2;
-- 尝试访问 logs 表(如果存在,会失败)
SELECT * FROM logs;

结果:

ERROR 1142 (42000): SELECT command denied to user 'table_user'@'localhost' for table 'logs'

操作后的数据状态(scores 表):

score_idemp_idscore
1190
3188

结果解读:

  • table_user 对 employees 表只有 SELECT 权限,只能查询不能修改。
  • table_user 对 scores 表有完整的读写删权限,但不能修改表结构(无 ALTER、DROP)。
  • table_user 无法访问 logs 表或其他任何表。
  • 表级权限存储在 mysql.tables_priv 表中。

第五步:清理

REVOKE ALL PRIVILEGES ON app_db.* FROM 'table_user'@'localhost';
DROP USER 'table_user'@'localhost';

场景四:授予列级权限(极少使用)

第一步:创建测试用户

CREATE USER 'column_user'@'localhost'
IDENTIFIED BY 'ColumnUser123!';

第二步:授予列级权限

-- 只能更新 employees 表的 dept 列
GRANT UPDATE(dept) ON app_db.employees TO 'column_user'@'localhost';

-- 可以查询 employees 表所有列
GRANT SELECT ON app_db.employees TO 'column_user'@'localhost';

第三步:查看授权结果

SHOW GRANTS FOR 'column_user'@'localhost';

操作后的权限状态:

Grants for column_user@localhost
GRANT USAGE ON . TO 'column_user'@'localhost'
GRANT SELECT ON app_db.employees TO 'column_user'@'localhost'
GRANT UPDATE (dept) ON app_db.employees TO 'column_user'@'localhost'

第四步:验证列级权限

以 'column_user'@'localhost' 连接数据库:

USE app_db;

-- SELECT 所有列(成功)
SELECT * FROM employees;

验证结果:

emp_idemp_namedeptscore
1大翔技术部100
2白歌技术部NULL
-- 更新 dept 列(成功)
UPDATE employees SET dept = '产品部' WHERE emp_id = 1;
-- 更新 score 列(失败,未授权)
UPDATE employees SET score = 95 WHERE emp_id = 1;

结果:

ERROR 1143 (42000): UPDATE command denied to user 'column_user'@'localhost' for column 'score' in table 'employees'
-- 更新 emp_name 列(失败,未授权)
UPDATE employees SET emp_name = '大翔翔' WHERE emp_id = 1;

结果:

ERROR 1143 (42000): UPDATE command denied to user 'column_user'@'localhost' for column 'emp_name' in table 'employees'

操作后的数据状态(employees 表):

emp_idemp_namedeptscore
1大翔技术部100
2白歌技术部NULL

结果解读:

  • column_user 成功更新了 emp_id = 1 的 dept 列。
  • 尝试更新 score 和 emp_name 列时被拒绝,错误信息明确指出了被拒绝的列名。
  • 列级权限存储在 mysql.columns_priv 表中。
  • 警告:列级权限会使权限表膨胀,增加认证开销。生产环境中建议通过视图控制列访问,而非列级权限。

第五步:清理

REVOKE ALL PRIVILEGES ON app_db.* FROM 'column_user'@'localhost';
DROP USER 'column_user'@'localhost';

场景五:GRANT OPTION(允许转授权限)

第一步:创建两个测试用户

CREATE USER 'senior_user'@'localhost'
IDENTIFIED BY 'SeniorUser123!';

CREATE USER 'junior_user'@'localhost'
IDENTIFIED BY 'JuniorUser123!';

第二步:授予 senior_user 权限及转授权

GRANT SELECT, INSERT ON app_db.* TO 'senior_user'@'localhost'
WITH GRANT OPTION;

第三步:查看 senior_user 权限

SHOW GRANTS FOR 'senior_user'@'localhost';

操作后的权限状态:

Grants for senior_user@localhost
GRANT USAGE ON . TO 'senior_user'@'localhost'
GRANT SELECT, INSERT ON app_db.* TO 'senior_user'@'localhost' WITH GRANT OPTION

第四步:senior_user 将权限转授给 junior_user

以 'senior_user'@'localhost' 连接数据库:

GRANT SELECT ON app_db.* TO 'junior_user'@'localhost';

第五步:查看 junior_user 权限

SHOW GRANTS FOR 'junior_user'@'localhost';

转授后的权限状态:

Grants for junior_user@localhost
GRANT USAGE ON . TO 'junior_user'@'localhost'
GRANT SELECT ON app_db.* TO 'junior_user'@'localhost'

第六步:验证 junior_user 权限

以 'junior_user'@'localhost' 连接数据库:

USE app_db;
SELECT * FROM employees;

验证结果:

emp_idemp_namedeptscore
1大翔技术部100
2白歌技术部NULL
-- 尝试 INSERT(失败)
INSERT INTO employees (emp_name) VALUES ('测试');

结果:

ERROR 1142 (42000): INSERT command denied to user 'junior_user'@'localhost' for table 'employees'

结果解读:

  • WITH GRANT OPTION 使 senior_user 拥有将已获权限授予其他用户的能力。
  • senior_user 只能转授自己拥有的权限(SELECT、INSERT),不能转授不存在的权限。
  • junior_user 只能从 senior_user 处获得 SELECT 权限,无法获得 INSERT(除非 senior_user 也转授了 INSERT)。
  • GRANT OPTION 是高级权限,应谨慎授予,避免权限扩散失控。

第七步:清理

REVOKE ALL PRIVILEGES ON app_db.* FROM 'senior_user'@'localhost';
REVOKE ALL PRIVILEGES ON app_db.* FROM 'junior_user'@'localhost';
DROP USER 'senior_user'@'localhost';
DROP USER 'junior_user'@'localhost';

场景六:存储过程级权限

第一步:创建存储过程

DELIMITER //

CREATE PROCEDURE app_db.GetEmployeeCount()
BEGIN
    SELECT COUNT(*) AS total_employees FROM app_db.employees;
END //

CREATE PROCEDURE app_db.GetHighScore(IN p_dept VARCHAR(20))
BEGIN
    SELECT emp_name, dept, e.score
    FROM app_db.employees e
    JOIN app_db.scores s ON e.emp_id = s.emp_id
    WHERE e.dept = p_dept
    ORDER BY s.score DESC
    LIMIT 1;
END //

DELIMITER ;

第二步:创建测试用户

CREATE USER 'proc_user'@'localhost'
IDENTIFIED BY 'ProcUser123!';

第三步:授予存储过程执行权限

GRANT EXECUTE ON PROCEDURE app_db.GetEmployeeCount TO 'proc_user'@'localhost';
GRANT EXECUTE ON PROCEDURE app_db.GetHighScore TO 'proc_user'@'localhost';

第四步:查看授权结果

SHOW GRANTS FOR 'proc_user'@'localhost';

操作后的权限状态:

Grants for proc_user@localhost
GRANT USAGE ON . TO 'proc_user'@'localhost'
GRANT EXECUTE ON PROCEDURE app_db.GetEmployeeCount TO 'proc_user'@'localhost'
GRANT EXECUTE ON PROCEDURE app_db.GetHighScore TO 'proc_user'@'localhost'

第五步:验证存储过程权限

以 'proc_user'@'localhost' 连接数据库:

-- 执行授权的存储过程(成功)
CALL app_db.GetEmployeeCount();

验证结果:

total_employees
2
-- 执行另一个授权的存储过程(成功)
CALL app_db.GetHighScore('技术部');

验证结果:

emp_namedeptscore
大翔技术部100
-- 尝试直接查询底层表(失败)
SELECT * FROM app_db.employees;

结果:

ERROR 1142 (42000): SELECT command denied to user 'proc_user'@'localhost' for table 'employees'

结果解读:

  • proc_user 没有 employees 表的直接 SELECT 权限,但通过 EXECUTE 权限可以调用存储过程。
  • 存储过程在创建者的权限上下文中执行(默认的 SQL SECURITY DEFINER),因此 proc_user 可以间接获取数据。
  • 这种机制非常适合"只允许通过特定接口访问数据"的场景,避免用户直接操作表。

第六步:清理

REVOKE EXECUTE ON PROCEDURE app_db.GetEmployeeCount FROM 'proc_user'@'localhost';
REVOKE EXECUTE ON PROCEDURE app_db.GetHighScore FROM 'proc_user'@'localhost';
DROP USER 'proc_user'@'localhost';
DROP PROCEDURE app_db.GetEmployeeCount;
DROP PROCEDURE app_db.GetHighScore;

场景七:创建只读用户

第一步:创建测试用户

CREATE USER 'readonly'@'localhost'
IDENTIFIED BY 'ReadOnly123!';

第二步:授予只读权限

GRANT SELECT ON app_db.* TO 'readonly'@'localhost';

第三步:验证只读权限

以 'readonly'@'localhost' 连接数据库:

USE app_db;

-- SELECT 成功
SELECT * FROM employees;
-- INSERT 失败
INSERT INTO employees (emp_name) VALUES ('测试');

结果:

ERROR 1142 (42000): INSERT command denied to user 'readonly'@'localhost' for table 'employees'
-- UPDATE 失败
UPDATE employees SET dept = '测试部' WHERE emp_id = 1;

结果:

ERROR 1142 (42000): UPDATE command denied to user 'readonly'@'localhost' for table 'employees'
-- DELETE 失败
DELETE FROM employees WHERE emp_id = 1;

结果:

ERROR 1142 (42000): DELETE command denied to user 'readonly'@'localhost' for table 'employees'

结果解读:

  • 只读用户是生产环境中最常见的权限配置之一,适用于报表查询、数据分析等场景。
  • 如果只需访问特定表,应精确到表级:GRANT SELECT ON app_db.employees TO 'readonly'@'localhost'。
  • 只读用户仍然可以看到表结构和数据,敏感数据应通过视图进一步控制。

第四步:清理

REVOKE ALL PRIVILEGES ON app_db.* FROM 'readonly'@'localhost';
DROP USER 'readonly'@'localhost';

权限生效时机

GRANT ...          -- 修改权限表
FLUSH PRIVILEGES;  -- 手动刷新(通常不需要,GRANT 自动刷新)

MySQL 5.7 中,GRANT、REVOKE、CREATE USER 等语句会自动触发权限刷新,一般不需要手动执行 FLUSH PRIVILEGES。

验证权限生效时机:

-- 创建新用户
CREATE USER 'test_timing'@'localhost' IDENTIFIED BY 'Test123!';

-- 立即授权
GRANT SELECT ON app_db.* TO 'test_timing'@'localhost';

-- 立即验证(无需 FLUSH PRIVILEGES)
-- 以 test_timing 连接,执行 SELECT,立即生效

结果解读:

  • GRANT 执行后会自动刷新权限缓存,新连接立即生效。
  • 已建立的连接通常也能立即感知权限变化,但某些客户端可能缓存了连接,需要重新连接才能生效。
  • 只有在直接修改系统权限表(如 UPDATE mysql.user)后,才需要手动执行 FLUSH PRIVILEGES。

常见误区

误区正解
GRANT ALL 包括所有权限不包括 GRANT OPTION,需额外授予。
REVOKE 会删除用户不会,只回收权限。用户还在,只是没权限了。
权限修改后立即对所有连接生效已建立的连接可能需要重新连接才能感知新权限。

面试考点

Q:GRANT ALL 和 GRANT ALL PRIVILEGES 的区别?

两者等价。ALL PRIVILEGES 是标准写法,ALL 是简写。都不包含 GRANT OPTION。

Q:如何创建一个只读用户?

GRANT SELECT ON database.* TO 'readonly'@'host';。如果只需访问特定表,精确到表级。

Q:FLUSH PRIVILEGES 什么时候需要?

直接修改权限表(如 UPDATE mysql.user)后需要手动刷新。正常使用 GRANT/REVOKE/CREATE USER 时自动刷新,不需要手动执行。

小结

  • 权限按层级分为全局、数据库、表、列、存储过程级
  • GRANT 授予权限,REVOKE 回收权限
  • 列级权限开销大,建议用视图替代
  • WITH GRANT OPTION 允许用户将权限转授他人,需谨慎使用
  • 遵循最小权限原则,只授予完成任务所需的最小权限集合
  • 完整流程:创建用户 → 精确授权 → 多维度验证 → 按需回收 → 定期审计

下一章引子:MySQL 5.7 引入了角色(Role),让权限管理从"一对一"升级为"一对多"。

上一页
用户管理
下一页
角色