MySQL原生不记录GRANT/REVOKE历史,需通过SHOW GRANTS查当前权限、解析binlog(STATEMENT/MIXED格式)、启用审计插件或自建审计表等方式追踪;注意FLUSH PRIVILEGES非必需,且权限撤销须对象粒度一致。

MySQL 原生不记录授权操作的历史(即 GRANT、REVOKE 的执行时间、执行人、变更前后的权限详情),所以直接查官方系统表无法获取授权历史。但可通过以下几种方式定位或补全权限变更线索。
查看当前生效的权限配置
这是排查权限问题的第一步,确认“现在用户到底有什么权限”:
-
查当前登录用户的全部权限:
SHOW GRANTS; -
查指定用户(含 host)的权限:
SHOW GRANTS FOR 'username'@'host';(如'admin'@'192.168.5.%') -
查用户在 mysql.user 表中的全局权限字段:
SELECT user, host, Select_priv, Insert_priv, Grant_priv, Super_priv FROM mysql.user WHERE user = 'username'; -
查某用户对特定数据库的权限:
SELECT * FROM mysql.db WHERE user = 'username' AND db = 'dbname'\G;
从二进制日志(binlog)回溯授权操作
如果开启了 binlog 且格式为 STATEMENT 或 MIXED,GRANT/REVOKE 语句会被记录(它们本质是 DDL 操作,会写入 binlog):
- 先确认是否启用:
SHOW VARIABLES LIKE 'log_bin';和SHOW VARIABLES LIKE 'binlog_format'; - 解析指定 binlog 文件:
mysqlbinlog /var/lib/mysql/mysql-bin.000001 | grep -i "grant\|revoke"; - 注意:需有文件系统读取权限;
ROW格式下不会记录 SQL 文本,不可用此法
启用审计日志或自建权限变更追踪
生产环境建议主动建设审计能力,因为依赖 binlog 不稳定且难关联操作人:
-
使用 MySQL 企业版审计插件(audit_log),可记录所有
GRANT/REVOKE及执行账号、时间、IP -
社区版替代方案:创建专用审计表 + 触发器或代理层拦截
例如,在管理节点部署轻量脚本,所有权限变更统一走封装命令(如mysql-grant --user=admin --to='u@%' --on=test.* --priv=SELECT),自动写入日志表 -
第三方工具辅助:如 Percona Toolkit 的
pt-query-digest分析慢日志(若权限语句被误记为慢查询)、或前述提到的 Python 权限审计工具包(带触发器+Web 界面+Excel 导出)
常见误操作与快速验证点
权限异常往往不是“没改过”,而是改得不完整或未刷新:
-
GRANT后忘记执行FLUSH PRIVILEGES;?—— 实际上GRANT自动重载权限表,无需手动 flush(仅修改mysql.user表直连更新时才需要) - 撤销权限时范围不匹配?例如
GRANT ALL ON *.*后用REVOKE ALL ON db1.*—— 会失败或无效,必须保持对象粒度一致(*.*对*.*) - 用户 host 匹配错误?比如创建了
'user'@'192.168.1.%',但连接时实际来源 IP 是192.168.2.100,则匹配不到该账户,自然无权限 - 密码过期或认证插件变更?
authentication_string非空但password_expired='Y'也会导致权限失效










