MySQL 8.0.16起引入系统用户与普通用户的本质区分,核心在于SYSTEM_USER权限控制:仅系统用户可修改root等关键账号,防止提权漏洞;该权限需显式授予且不可被普通DBA转授。

MySQL里没有“用户”和“账户”的本质区别——user 就是账户,账户就是 user,二者是同一概念在不同语境下的说法。 所谓“用户”指的就是能连上 MySQL 实例、带用户名+主机名+密码+权限的一套认证实体;所谓“账户”只是更偏运维/安全角度的叫法。真正有区分意义的是“系统用户”和“普通用户”,这是从 MySQL 8.0.16 起引入的权限层级控制机制,不是命名习惯问题,而是安全策略落地的关键。
为什么必须区分“系统用户”和“普通用户”?
这不是为了分类而分类,而是为堵住一个真实存在的提权漏洞:
- 在 MySQL 8.0.16 之前,只要用户有
CREATE USER或SUPER权限,就能DROP USER 'root'@'localhost'—— 真的能删掉 root - 也能执行
ALTER USER 'root'@'localhost' IDENTIFIED BY 'xxx',直接劫持最高权限账号 - 攻击者一旦拿下一个有
GRANT OPTION的 DBA 账号,就等于拿下了整个实例
引入 SYSTEM_USER 权限后,上述操作是否生效,不再只看有没有 CREATE USER,而要看执行者自己是不是“系统用户”。它像一道闸门:没这把钥匙,连 root 的密码都改不了。
怎么判断一个账号是不是“系统用户”?
查 mysql.user 表里的 System_user 字段(注意大小写),或者用 SHOW GRANTS 看是否含 SYSTEM_USER 权限:
SELECT User, Host, System_user FROM mysql.user;
或
SHOW GRANTS FOR 'admin'@'%';
输出中若含 GRANT SYSTEM_USER ON *.* TO ...,就是系统用户。注意:SYSTEM_USER 是独立权限,不附带任何其他能力(比如不能 SELECT、不能 CREATE DATABASE),它只管“能不能动系统级账号”这一件事。
创建/修改系统用户时最容易踩的坑
-
CREATE USER本身不授予SYSTEM_USER权限,必须显式GRANT:CREATE USER 'sysop'@'%' IDENTIFIED BY 'p@ssw0rd'; GRANT SYSTEM_USER ON *.* TO 'sysop'@'%';
- 普通用户即使有
CREATE USER,也无法给他人授SYSTEM_USER权限(会报错ERROR 1045 (28000): Access denied) - 用
ALTER USER ... REQUIRE ISSUER等高级认证选项修改系统用户时,执行者也必须是系统用户,否则直接拒绝 - MySQL 8.0.16+ 默认 root 是系统用户,但如果你用
mysqld --initialize初始化后手动改过 root 密码,没补GRANT SYSTEM_USER,它可能已降级为普通用户——此时你反而无法再用 root 去管理其他系统用户
真正容易被忽略的是:系统用户的“系统性”不体现在登录方式或存储位置,而完全由权限位控制;它不改变账号结构(仍是 'user'@'host'),也不影响连接行为,只在执行特定 DDL 操作时动态拦截。别被名字带偏——重点永远是权限表里那一个 Y 或 N。










