mysql 8.0.16 及以后版本 中引入的一项重要安全机制:用户账户分类(account categories),通过 system_user 权限来区分 系统用户(system user) 和 普通用户(regular user)。
下面我将用中文为你逐层解析、通俗易懂地解释这段内容的核心思想和实际意义,帮助你真正“理解”它。
一、核心概念:什么是“系统用户”和“普通用户”?
从 mysql 8.0.16 开始,mysql 把用户分为两类:
| 类型 | 判断标准 | 俗称 |
|---|---|---|
| 系统用户(system user) | 拥有 system_user 权限的用户 | “高权限管理员” |
| 普通用户(regular user) | 没有 system_user 权限的用户 | “一般管理员或应用用户” |
✅ 注意:system_user 是一个独立的权限,它不赋予任何其他操作能力(比如建表、查数据),它的作用是控制谁能管理“系统级账户”。
二、为什么要分“系统用户”和“普通用户”?—— 安全隔离
问题背景:
在早期版本中,只要一个用户有 create user 或 super 权限,他就可以:
- 创建/删除/修改任何用户(包括 root)
- 终止任何会话(包括 dba 的连接)
- 设置存储过程的
definer为 root
这就导致了一个严重问题:
👉 一个“普通管理员”可能误删 root 账户,或者被攻击者利用提权,造成整个数据库失控。
解决方案:
引入 system_user 权限作为“守门员”,实现权限的层级控制。
三、关键规则总结(重点!)
✅ 规则 1:谁可以改谁?
| 操作者身份 | 能否修改“系统用户”? | 能否修改“普通用户”? |
|---|---|---|
| 系统用户(有 system_user) | ✅ 可以(需其他权限配合) | ✅ 可以 |
| 普通用户(无 system_user) | ❌ 不可以 | ✅ 可以 |
📌 举例:
- 用户 a 是普通用户,拥有
create user权限 → 他只能创建/修改/删除其他“普通用户”,不能动 root。 - 用户 b 是系统用户,拥有
create user→ 他可以操作所有用户,包括 root。
这就像公司里的“超级管理员”和“部门管理员”:
- 部门管理员可以管理本部门员工账号;
- 但不能动 ceo 或总管理员的账号;
- 只有超级管理员才能动 ceo 的账号。
✅ 规则 2:哪些操作受system_user限制?
以下操作如果涉及“系统用户”,执行者必须自己也是“系统用户”:
| 操作 | 说明 |
|---|---|
| 账户管理(create user, grant, alter user, drop user) | 修改系统用户的密码、权限、认证方式等,必须由系统用户操作 |
| 终止会话(kill) | 你想 kill 一个系统用户的连接?你也得是系统用户才行! |
| 设置 definer | 如果你想让一个存储过程/视图以“系统用户”身份运行(definer = 'root'@'localhost'),那你必须有 system_user 权限 |
| 设置 mandatory_roles | 不能把“系统用户角色”设为强制角色(避免所有用户自动获得高权限) |
| 审计豁免(mysql enterprise audit) | 从 8.0.28 起,系统用户自动获得 audit_abort_exempt,即使审计规则禁止某些查询,系统用户仍可执行 —— 这是为了防止审计配置错误导致“完全无法登录”的灾难 |
四、“会话”也有系统/普通之分
不仅用户分类型,当前连接的“会话”也分类型:
- 会话是否为“系统会话”,取决于:
- 当前用户的账号是否有
system_user - 或者当前激活的角色中是否有包含
system_user的角色
- 当前用户的账号是否有
会话可以动态变化!
-- 当前是普通会话 set role admin_role; -- 如果 admin_role 包含 system_user -- 现在变成了系统会话! -- 再取消角色 set role none; -- 又变回普通会话了
📌 注意:
- 权限变更(如
grant system_user to user)只对新连接生效,不影响已存在的会话。 - 存储过程执行时,继承的是调用它的会话类型,而不是 definer 是否是系统用户。
五、如何保护系统账户不被普通用户篡改?(实战建议)
仅仅不让普通用户有 system_user 权限还不够!因为还有另一种方式可以改用户信息:
⚠️ 直接修改 mysql 系统数据库中的表(如 mysql.user)!
所以,为了彻底保护系统账户,你需要双重防护:
✅ 防护策略 1:禁止普通用户操作mysql表
即使用户有 all privileges on *.*,也可以通过 partial revoke(部分撤销) 剥夺其对 mysql 库的操作权。
示例:创建一个“全能但安全”的普通管理员 u1
-- 1. 创建用户 create user u1 identified by 'password'; -- 2. 授予全局所有权限(包含 system_user) grant all on *.* to u1 with grant option; -- 3. 撤销 system_user —— 让 u1 成为普通用户 revoke system_user on *.* from u1; -- 4. 撤销对 mysql 系统库的所有修改权限 -- 防止他直接 insert/update mysql.user 来绕过限制 revoke all on mysql.* from u1;
✅ 结果:
- u1 可以管理所有数据库、所有普通用户;
- 但不能修改系统用户(如 root);
- 也不能直接改
mysql.user表来“偷渡”; - 完全安全!
更精细的权限控制示例:
示例 1:只允许读mysql表(用于监控)
create user monitor identified by 'pass'; grant select, insert, update, delete on *.* to monitor; revoke insert, update, delete on mysql.* from monitor; -- monitor 可以读 mysql.user、mysql.db 查用户信息,但不能改
示例 2:只允许看特定字段
create user auditor identified by 'pass'; grant all on *.* to auditor; revoke all on mysql.* from auditor; grant select on mysql.db to auditor; grant select (host, user) on mysql.user to auditor; -- 只能查看 user 表的 host 和 user 字段
六、常见问题解答(faq)
❓ q1:system_user和super有什么区别?
| 特性 | system_user | super(已弃用) |
|---|---|---|
| 功能 | 控制是否能操作“系统用户” | 旧时代的万能权限,几乎无所不能 |
| 精细度 | 更细粒度,专用于账户管理隔离 | 太粗放,容易造成权限泛滥 |
| 推荐 | ✅ 推荐使用 | ⚠️ 已标记为 deprecated,未来会被移除 |
💡
super正在被拆解成多个专用权限(如connection_admin,system_user,set_user_id等),这是 mysql 权限体系现代化的一部分。
❓ q2: root 用户是系统用户吗?
✅ 是的!默认的 root@localhost 在 mysql 8.0+ 中会被自动赋予 system_user 权限,属于系统用户。
❓ q3: 我怎么查看某个用户有没有system_user权限?
-- 查看用户权限 show grants for 'username'@'host'; -- 或查询 mysql.user 表 select user, host, system_user from mysql.user where user = 'root';
注意:字段名是 system_user(在 mysql.user 表中),值为 'y' 或 'n'。
七、总结:一句话理解
🔐 system_user 权限是一个“守门员”,它决定了一个用户是否有资格去管理和影响那些“更高权限的系统账户”(如 root),从而实现了权限的层级隔离,提升了数据库的安全性。
🛡️ 实际建议(给 dba 的最佳实践)
- 只给真正需要的 dba 分配 system_user 权限
- 普通运维人员、应用管理员应设为“普通用户”
- 使用 partial revoke 禁止普通用户访问 mysql 系统库
- 避免使用 super,改用细粒度权限(如 connection_admin, system_user)
- 定期审计谁有 system_user 权限
如果你是数据库管理员,这个机制就像是给你的“保险箱”加了一把锁:
🔑 普通员工可以处理日常事务,但动不了保险箱(root 账号);
🔐 只有拿着特定钥匙(system_user)的人才能打开。
这样,即使有人拿到管理员账号,也无法轻易破坏核心系统。
如有具体场景(比如你想创建一个“受限管理员”),我可以帮你写具体的 sql 示例。
到此这篇关于mysql用户账户分类的使用的文章就介绍到这了,更多相关mysql用户账户分类内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论