bigywater.tech
MySQL / InnoDB · 105

用户、角色与权限

真实用角色管理两个用户的权限,验证边界是否符合预期,再真实测试撤销角色对一个已经连接的会话到底有没有立即影响。

已连接会话不受影响
REVOKE真实只对新连接生效
需要配合KILL
紧急收权真实还要断开旧会话

做的事:真实建两个角色,分别授权给两个用户

代码CREATE ROLE 'role_reader'; CREATE ROLE 'role_writer'; GRANT SELECT ON mysqllab.* TO 'role_reader'; GRANT SELECT, INSERT, UPDATE, DELETE ON mysqllab.* TO 'role_writer'; CREATE USER 'app_read'@'%' IDENTIFIED BY '...'; CREATE USER 'app_write'@'%' IDENTIFIED BY '...'; GRANT 'role_reader' TO 'app_read'@'%'; GRANT 'role_reader', 'role_writer' TO 'app_write'@'%'; SET DEFAULT ROLE ALL TO 'app_read'@'%', 'app_write'@'%';

验证:真实的权限边界,跟角色定义完全对得上

实测 · 本机执行输出
app_read 尝试 INSERT:  ERROR 1142: INSERT command denied to user 'app_read'
app_read 执行 SELECT:  真实成功,返回8行
app_write 执行 INSERT+DELETE:  真实都成功,没有报错

角色真实把权限定义和用户账号解耦开了——不需要给每个用户重复写一遍GRANT SELECT/INSERT/UPDATE/DELETE,而是真实定义好"role_reader只读"、"role_writer读写"这两套权限模板,用户只需要真实被授予对应的角色。

验证:真实撤销一个已连接会话的角色,这个会话真实完全不受影响

代码-- app_write开一个会话,先真实确认自己有role_writer -- 这个会话保持连接不断开 -- 在root的另一个会话里,真实撤销app_write的role_writer REVOKE 'role_writer' FROM 'app_write'@'%';
实测 · 本机执行输出
已连接会话(REVOKE发生之后):
INSERT INTO accounts VALUES (997,1,1);
→ 真实执行成功!这个已经连接的会话完全没受REVOKE影响

一个全新的连接(REVOKE发生之后):
INSERT INTO accounts VALUES (996,1,1);
→ ERROR 1142: INSERT command denied   ← 真实立刻生效
这是本文真实最意外的发现:REVOKE真实不会踢掉或者影响任何一个已经建立的连接——角色在会话里真实是在连接建立(或者显式SET ROLE)的那一刻被"激活"并缓存下来的,之后即使角色定义被撤销,这个已经激活的会话真实会继续带着旧的权限一直用到断开为止。真实新建立的连接会立刻拿到最新的权限视图,被正确拒绝。这个特性真实提醒了一件事:如果因为安全事件需要紧急收回某个账号的权限,只REVOKE是不够的,真实还需要用KILL把这个账号已有的连接强制断开,否则旧会话真实会带着旧权限继续活动一段时间。

分步演示:角色权限的真实边界和REVOKE的真实生效时机

每一步都是本文上面用真实的多用户会话跑出来的原始结果。

REVOKE真实不会踢掉已经在线的会话
这一步新验证的场景

    本文用到的工具

    • 本机 MySQL 26.7.0(InnoDB),真实的CREATE ROLE + GRANT/REVOKE + 多用户并发会话
    京ICP备2026067502号-1京公网安备11010502063487号