MySQL 8.0角色机制需人工完成启用开关、创建角色、赋权、绑定用户、设置默认角色五步,缺一不可;否则权限无法生效或导致越权。

MySQL 8.0 的角色机制本身不自动分级,必须靠人工定义角色边界 + 显式绑定 + 默认激活三者配合,否则开发和测试账号权限完全一样,甚至可能互相越权。
CREATE ROLE 必须先开全局开关,否则直接报错 ERROR 3719
执行 CREATE ROLE 'dev_role' 就失败?不是语法问题,是 MySQL 8.0 默认关闭角色支持。root 用户必须先运行:
SET GLOBAL activate_all_roles_on_login = ON;GRANT ROLE_ADMIN ON *.* TO 'admin_user'@'%';FLUSH PRIVILEGES;
生产环境务必在 my.cnf 的 [mysqld] 段追加 activate_all_roles_on_login=ON,否则重启后所有角色失效。
GRANT 权限给角色 ≠ GRANT 权限给用户,混淆会导致权限不可见
常见错误是把测试库权限直接授给用户:GRANT SELECT ON test_db.* TO 'test_user'@'%';——这绕过了角色体系,后续无法统一回收或替换。
正确做法分两步,且顺序不能反:
- 先填充角色:
GRANT SELECT, INSERT, UPDATE ON dev_db.* TO 'dev_role'@'%';(注意主机名用'%',避免后续匹配失败) - 再填充测试角色:
GRANT SELECT, EXECUTE ON test_db.* TO 'test_role'@'%';(EXECUTE是为了调用测试用的存储过程) - 禁止列级授权:
GRANT SELECT(id) ON t1 TO 'test_role'会报 ERROR 1142,角色不支持
角色名含短横线(如 'ci-tester')必须用反引号:GRANT SELECT ON logs.* TO `ci-tester`;
SET DEFAULT ROLE 是权限生效的临门一脚,漏掉就 Access denied
执行完 GRANT 'dev_role' TO 'zhangsan'@'%'; 后,用户登录仍被拒,SELECT CURRENT_ROLE(); 返回 NULL——几乎肯定是没执行这步:
-
SET DEFAULT ROLE 'dev_role' TO 'zhangsan'@'%';(host 必须严格匹配,'zhangsan'@'localhost'不能设'zhangsan'@'%'的默认角色) - 一个用户可叠加多个角色:
SET DEFAULT ROLE 'dev_role', 'test_role' TO 'zhangsan'@'%';,但要确认业务真需要读写开发库+执行测试库 - 普通用户无权执行
SET DEFAULT ROLE,需管理员具备SYSTEM_VARIABLES_ADMIN或APPLICATION_PASSWORD_ADMIN权限
验证是否真生效,别只看 SHOW GRANTS FOR 'zhangsan'@'%';——它只显示绑定关系。要查角色带来的实际权限:SHOW GRANTS FOR 'zhangsan'@'%' USING 'dev_role';
测试环境误用 WITH GRANT OPTION 会污染权限边界
有人想让测试负责人能“代授”测试角色,于是执行:GRANT 'test_role' TO 'qa_lead'@'%' WITH GRANT OPTION;——这是错的,WITH GRANT OPTION 只对用户有效,且会授予其所有权限的转授权,极易越界。
正确方式是用 WITH ADMIN OPTION:
GRANT 'test_role' TO 'qa_lead'@'%' WITH ADMIN OPTION;- 此时
qa_lead只能执行GRANT 'test_role' TO ...,不能授SELECT ON *.*或其他角色 - 该选项只对角色有效,且必须显式激活才能起作用:用户登录后仍需
SELECT CURRENT_ROLE();确认非空
开发与测试权限真正隔离的关键,不在角色名起得多清楚,而在于每一步是否都严格走完:开关启用 → 角色创建 → 角色赋权 → 用户绑定 → 默认激活 → 验证生效。少任何一环,分级就形同虚设。


















