数据库权限模型基础:用户、角色、权限

权限管理这个东西,刚入行时觉得就是几条 SQL 语句的事,直到我在一次生产事故里,因为一个用户权限配置错了,导致整个开发组读不了数据……那会儿我才真正琢磨透用户、角色、权限这三者之间到底该怎么搭。说白了,数据库权限模型就是一套规则,告诉你谁能碰什么、能碰多少。

1. 用户(User)—— 身份象征

每个数据库用户对应一个登录账户,就像你公司的工牌。用户是权限的最终载体,所有的操作最后都会落到某个用户头上。我个人习惯把用户分成几类:DBA 用户、应用服务用户、只读查询用户。千万不要一套账号打天下——我在项目里见过有人直接用 root 跑业务查询,后来出了事连谁干的都查不到。

  • 认证方式:密码、证书、操作系统认证……不同数据库支持不同方式。
  • 默认 Schema:用户登录后默认看到的对象集合。
  • 系统账户 vs 业务账户:系统账户(如 sa、sys)权限极高,业务账户应限制在最小必要范围。

2. 权限(Privilege)—— 操作许可

权限就是数据库告诉你:“你可以在某张表上 SELECT,但不能 DELETE。” 权限分两大类,我画了个表方便对比:

类型 作用范围 例子
系统权限 整个数据库实例 CREATE TABLE, ALTER DATABASE, CREATE USER
对象权限 具体的表、视图、存储过程等 SELECT ON employees, EXECUTE ON proc_salary

你想想看,如果每个表我都单独给用户授权,系统里几十个用户、几百张表,那授权语句不得写成千上万条?所以才有了角色这玩意儿。

3. 角色(Role)—— 权限的集合

角色就是一组权限的打包。比如我创建一个叫 readonly 的角色,里面塞了所有业务表的 SELECT 权限。然后我把这个角色授给几个查询用户,下次要加一个新表进去,只需要改角色的权限定义,不用找每个用户重新授权——爽不爽?

角色还可以嵌套。我记得在 Oracle 里就允许角色包含另一个角色,形成权限的层级。但要小心,嵌套太深容易让人搞不清到底谁有什么权限,我一般不建议超过两层。

命名规范建议:角色名用 role_ 前缀 + 业务含义,比如 role_report_select、role_app_rw。这样一眼就能看出这个角色的用途。

4. 三者之间的关系

先把核心关系捋清楚:用户 被授予 角色,角色 包含 一组权限,权限 允许 用户对数据库对象执行特定操作。授权路径是:
用户 → 角色(可选)→ 权限 → 对象操作

下面这张图概括了基本结构,我在做审计方案时经常拿它来跟团队对齐思路。

数据库权限模型核心概念 用户 (User) 角色 (Role) 权限 (Privilege) 对象 (Object) 操作 (Operation) 被授予 包含 作用于 定义 通过角色简化权限管理 避免直接给用户授权

实际授权操作,用 SQL 写出来就是:

-- 创建角色
CREATE ROLE developer;

-- 给角色授权(系统权限)
GRANT CREATE TABLE TO developer;
GRANT CREATE VIEW TO developer;

-- 给角色授权(对象权限)
GRANT SELECT, INSERT ON employees TO developer;
GRANT EXECUTE ON salary_proc TO developer;

-- 把角色授予用户
GRANT developer TO alice;

5. 一些踩过坑后的经验

  • 千万别给用户直接授对象权限。我曾经在一个老系统里,开发人员直接一个个表授权,后来离职交接,没人知道谁到底有什么权限。换成角色后,审计直接扫角色定义就清楚了。
  • 角色也可以有 WITH ADMIN OPTION,允许用户再把角色转授给别人。这个选项要谨慎,我见过一个报表组因为互相转授角色,最后权限膨胀得失控。
  • 权限最小化原则:只给够用的权限。比如查询用户只给 SELECT,不需要 UPDATE。
注意:不同数据库对角色和权限的实现有细微差别。比如 MySQL 的 ROLE 在 8.0 才正式引入,Oracle 里角色可以有密码,PostgreSQL 中用 GROUP 类似角色。迁移时一定要确认兼容性。

好了,基础概念就聊这些。理解用户、角色、权限的三角关系后,后面我们讲 SQL 审计时,你就能明白为什么要盯着角色变化去审计了。