mysql中查拥有相同权限组合的用户需用show grants生成标准化语句,排序后取sha256哈希比对,因系统无原生用户组概念,且直接查系统表易漏空值;角色权限需显式展开(using子句或查information_schema.applicable_roles),通配符主机名视为不同用户,哈希须定期更新。

查哪些用户拥有相同权限组合
MySQL本身不提供“用户组”概念,所谓“相同权限的用户组”实际是手动归类的结果。真正能查的是:哪些用户被授予了完全一致的权限集合(包括库、表、列级别)。核心思路是把每个用户的权限转成可比对的字符串标识。
关键点在于 INFORMATION_SCHEMA.ROLE_ROUTINE_GRANTS 并不存在(MySQL 8.0+ 才有角色支持),所以得从 mysql.user、mysql.db、mysql.tables_priv 等系统表拼出完整权限快照。但直接 JOIN 这些表容易漏掉空值或 NULL 权限字段,导致误判。
- 优先用
SHOW GRANTS FOR 'user'@'host'生成标准化语句,再哈希比对——这是最可靠的方式 - 不要依赖
SELECT * FROM mysql.user WHERE Select_priv='Y'这类粗粒度查询,它无法反映 db/table 级权限差异 - 注意
mysql.user中的plugin和account_locked不影响权限判定,别混进去
用哈希聚合快速识别权限相同的用户
把每个用户的全部 SHOW GRANTS 输出排序后取 SHA256,就能把权限一致的用户归到同一 hash 值下。这个操作不能在 SQL 里直接做(因为要执行动态语句),得靠脚本中转。
示例 Python 片段逻辑:
import hashlib
import subprocess
<p>def get_grants_hash(user_host):
cmd = ["mysql", "-N", "-s", "-e", f"SHOW GRANTS FOR {user_host};"]
output = subprocess.check_output(cmd).decode().strip()</p><h1>排序确保语句顺序不影响 hash</h1><pre class="brush:php;toolbar:false;">lines = sorted(output.split("\n"))
return hashlib.sha256("\n".join(lines).encode()).hexdigest()对所有用户循环调用,存入 dict: {hash: [user1, user2]}
-
mysql -N -s去掉列头和制表符,避免格式干扰哈希 - 必须
sorted(),否则GRANT SELECT ON a.*和GRANT SELECT ON b.*顺序不同会导致 hash 不同 - MySQL 8.0+ 用户可能有
AS 'role_name'语法,也要纳入比对范围
处理角色(Role)带来的嵌套权限
如果用了 MySQL 8.0 的角色机制,SHOW GRANTS FOR 'u'@'h' 默认不展开角色权限,只显示直接授予的内容。这会导致两个用户明明通过不同角色获得相同权限,却被判为不一致。
- 必须加
SHOW GRANTS FOR 'u'@'h' USING role1, role2;才能展开角色链 - 但角色名未知时,得先查
mysql.role_edges表递归找出所有激活角色 - 更稳妥的做法是统一用
SELECT * FROM INFORMATION_SCHEMA.APPLICABLE_ROLES获取当前用户有效角色集 - 注意
ACTIVE_ROLE只在会话中生效,脚本里需模拟 SET ROLE 操作才能还原真实权限视图
权限对比时最容易忽略的细节
很多团队以为“SELECT + INSERT 权限一样”就算同组,但实际生产中以下几点常导致误判:
-
WITH GRANT OPTION是独立权限位,带和不带算两种权限组合 -
CREATE VIEW和CREATE ROUTINE在mysql.user表里是单独字段,但SHOW GRANTS会合并输出,需确认是否被正确解析 - 通配符主机名如
'user'@'%'和'user'@'192.168.%'即使权限完全一样,也属于不同用户实体,不应强行合并 - MySQL 5.7 和 8.0 的权限字段命名有差异(比如
Trigger_privvsTRIGGER),跨版本比对前必须标准化输出格式
权限哈希不是一劳永逸的快照,只要任意用户执行过 GRANT 或 REVOKE,就得重新计算全量哈希。线上环境建议配合 binlog 解析或审计日志做增量更新,而不是每次全扫。











