人人都会AI编程

23.2 权限体系:全局权限、库级权限、表级权限、列级权限

更新时间:2026-07-11

MySQL 的权限控制非常精细,它不只是在“谁能登录”这个层面做文章,而是可以精确到“谁能在哪个表甚至哪个列上执行什么操作”。实际生产环境中,账号泄露或误操作往往是权限分配不当导致的,掌握这套体系是安全管理的必修课。

MySQL 将权限划分为多个层级,从大到小分别是全局级、数据库级、表级、列级,此外还有存储过程和代理权限等更细的分支。权限信息存储在系统数据库 mysql 的几张核心表中,通过 GRANTREVOKE 语句管理,修改后通常需要执行 FLUSH PRIVILEGES 使其生效,但在 8.0 中已经基本不需要了,因为动态权限表已由服务器自动重载。

全局权限(Global Level)

全局权限作用于整个 MySQL 服务器,对所有数据库、所有表都有效。这类权限授予时需要格外谨慎,往往只给 DBA 或系统管理账号。

常用的全局权限包括:

  • ALL PRIVILEGES:所有权限的集合,拥有它就等于 root
  • CREATE USER:创建、删除、重命名用户。
  • FILE:允许执行 SELECT ... INTO OUTFILELOAD DATA 等读写服务器文件系统的操作。务必严格控制,否则可能有数据泄露风险。
  • PROCESS:允许查看所有连接线程信息(SHOW PROCESSLIST),可看到其他用户正在执行的 SQL 语句。
  • RELOAD:允许执行 FLUSH 操作刷新日志、缓存等。
  • REPLICATION CLIENTREPLICATION SLAVE:主从复制相关。
  • SHUTDOWN:允许执行 SHUTDOWN 关闭数据库服务器。
  • SUPER(8.0 中已拆分为多个更细的权限):允许执行全局修改变量的操作,如 CHANGE MASTERKILL 其他线程。8.0 后建议使用 SYSTEM_VARIABLES_ADMINCONNECTION_ADMIN 等更安全的权限替代。

授予全局权限的语法是在 GRANT 后加上 ON .(表示所有库所有表):

-- 创建一个管理账号,仅允许从特定IP连接,并赋予全局处理权限
CREATE USER 'dba_user'@'192.168.1.%' IDENTIFIED BY 'StrongPass123!';
GRANT PROCESS, REPLICATION CLIENT ON *.* TO 'dba_user'@'192.168.1.%';

数据库级权限(Database Level)

数据库级权限控制对某个特定数据库(或部分数据库)中所有对象的操作。这是最常用的授权级别,通常应用程序账号会拥有业务库的全部常规操作权限,但不应触及 mysqlsys 等系统库。

常用的库级权限包括:

  • CREATE:在指定库中创建新表。
  • DROP:在指定库中删除表或视图。
  • ALTER:修改表结构(如 ALTER TABLE)。
  • SELECT, INSERT, UPDATE, DELETE(统称增删改查权限)。
  • INDEX:创建或删除索引。
  • CREATE VIEW, SHOW VIEW:创建和查看视图定义。
  • CREATE ROUTINE, ALTER ROUTINE, EXECUTE:管理存储过程和函数。

授予数据库级权限使用 ON database_name.* 语法,表示该库下的所有表:

-- 给应用账号授予在业务数据库 order_db 中常用的操作权限
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, INDEX, ALTER, DROP
ON order_db.*
TO 'app_user'@'10.0.0.%';

如果需要对某个数据库做严格管控,比如只允许读取,绝不允许修改和删表,就可以只授 SELECT

表级权限(Table Level)

表级权限限制在某个数据库的某一张或某几张具体表上。这在多团队共用同一库,或需要隔离敏感表时非常有用。比如客服部门只需要看用户信息但不让看密码字段,可以在表级或列级进一步收拢权限。

可授予的表级权限与库级大致相同(SELECT, INSERT, UPDATE, DELETE, ALTER, INDEX, DROP 等),但作用范围缩小到表。

授予表级权限的语法是 ON database_name.table_name

-- 允许只读访问 user_profile 表
GRANT SELECT ON app_db.user_profile TO 'readonly_user'@'%';

-- 允许对 order 表做增删改查,但无法修改其结构
GRANT SELECT, INSERT, UPDATE, DELETE ON app_db.orders TO 'order_app'@'%';

可以对多个表单独写多条 GRANT,也可以一次授予同一个库的多张表权限。

列级权限(Column Level)

列级权限可以精确到某张表的某个列(字段),这是 MySQL 中最细粒度的权限控制。不过它的使用场景比较有限,因为列级权限只能用于 SELECT, INSERT, UPDATE 三种操作,而且只能限制列,不能限制行(行级安全 MySQL 原生不支持,需要靠视图或应用逻辑实现)。

实际中,列级权限常用于屏蔽敏感列,比如只有少数人能看到员工薪资或用户密码哈希:

-- 授予对 employee 表的大部分列有 SELECT 权限,但对 salary 列无权限
REVOKE SELECT ON company.employee FROM 'hr_user'@'%';
GRANT SELECT (id, name, department, position) ON company.employee TO 'hr_user'@'%';

注意,列级权限一旦使用,会使权限管理变得复杂,因为它改变了默认的全表 SELECT 行为。如果 hr_user 执行 SELECT FROM employee,将会报错,因为 隐含了 salary 列,而用户没有其 SELECT 权限。所以要么严格控制查询代码,要么通过视图隐藏敏感列,再用表级权限授权给该用户只读视图。

权限管理的实用要点

  1. 最小权限原则:永远只授予刚好完成工作所需的权限。不要给开发环境账号开启 SUPERFILEDROP 数据库等危险权限。
  2. 主机限制:创建用户时一定要限定可连接的来源 IP(或网段),避免账号在网络中裸奔。'username'@'%' 允许从任意 IP 连接,除非绝对必要,否则不要用 %
  3. 权限查看:可以通过 SHOW GRANTS FOR 'user'@'host'; 查看某个用户的完整权限列表。检查权限是否分配正确的最快方法就是这个命令。
  4. 回收权限REVOKE 的语法与 GRANT 基本相同,只是把 TO 换成 FROM。比如 REVOKE DELETE ON order_db.* FROM 'app_user'@'%'; 会收回该用户对 order_db 所有表的删除权限。
  5. 动态权限(8.0+):8.0 引入了一些更细粒度的动态权限,如 SESSION_VARIABLES_ADMINCONNECTION_ADMIN,它们是全局性的,但比老式的 SUPER 安全得多。建议逐步用它们替代旧的超级权限。
  6. mysql 系统表:权限数据存储在 mysql.user(全局权限和用户信息)、mysql.db(库级权限)、mysql.tables_priv(表级权限)、mysql.columns_priv(列级权限)等表中。一般情况下不直接修改这些表,而是通过 GRANT/REVOKE 操作。
  7. 常见组合建议
  • 日常开发只读账号:全局可连接,特定数据库的 SELECTSHOW VIEW
  • 业务应用账号:特定数据库的 SELECT, INSERT, UPDATE, DELETE,以及 CREATE TEMPORARY TABLESINDEX 等。
  • 日报/BI 提取账号:特定库或表的 SELECT,配合 REPLICATION CLIENT 用于检测延迟。
  • 备份账号SELECTRELOADLOCK TABLES(或用 XtraBackup 需要 SUPERPROCESS)。

掌握了这四层权限体系,你可以为团队搭建出安全、清晰、可控的数据库访问架构。这对于防止线上数据被误删或泄露,是非常实际且必要的防线。