用select查询当前所有用户权限需查mysql.user、mysql.db等5张系统表,mysql 5.7与8.0字段差异大;推荐用mysqlpump/mysqldump导出grant语句审计,或用事件调度器定时存档至privs_snapshot表。

如何用 SELECT 查询当前所有用户权限
MySQL 没有内置“权限审计日志”功能,最直接的审计起点是查 mysql.user、mysql.db、mysql.tables_priv 等系统表。注意:不同 MySQL 版本(5.7 vs 8.0)字段名和权限存储方式有差异。
常用查询示例:
SELECT host, user, authentication_string, account_locked, password_expired FROM mysql.user WHERE user != 'mysql.sys';
关键点:
-
mysql.user存的是全局权限和账户状态,但Super_priv、Grant_priv这类字段是Y/N字符串,不是布尔值 - MySQL 8.0+ 用
authentication_policy和password_reuse_history等新字段控制密码策略,5.7 不支持 - 直接 SELECT 系统表需
SELECT权限 onmysql.*,普通用户默认无权访问 —— 审计脚本必须用高权限账号运行
用 mysqlpump 或 mysqldump 导出权限语句做版本比对
比起查原始表,更实用的方式是导出可读的 GRANT 语句,便于人工审查或 diff 工具比对历史快照。
推荐命令(MySQL 8.0+):
mysqlpump --no-data --skip-definer --users > /tmp/privs_$(date +%F).sql
说明:
-
--no-data只导结构和权限,不导表数据 -
--skip-definer避免导出DEFINER引发的权限错误 - MySQL 5.7 不支持
mysqlpump,改用mysqldump -u root -p --all-databases --no-data --skip-triggers --ignore-table=%.tables_priv,再手动过滤GRANT行 - 导出结果里
CREATE USER和GRANT是分离的,需确保两者顺序一致,否则导入时可能报ERROR 1396 (HY000)
用事件调度器(Event Scheduler)自动执行权限快照
MySQL 自带的 EVENT 可定时执行 SQL,适合定期存档权限状态。但注意它不能直接写文件,需配合表存储。
实操步骤:
- 先建存档表:
CREATE TABLE IF NOT EXISTS mysql.privs_snapshot ( id BIGINT PRIMARY KEY AUTO_INCREMENT, snap_time DATETIME DEFAULT CURRENT_TIMESTAMP, host VARCHAR(255), user VARCHAR(128), select_priv ENUM('N','Y'), insert_priv ENUM('N','Y'), grant_priv ENUM('N','Y'), ssl_type VARCHAR(64) ) ENGINE=InnoDB; - 创建事件(每天凌晨 2 点执行):
CREATE EVENT IF NOT EXISTS save_user_privs ON SCHEDULE EVERY 1 DAY STARTS '2024-01-01 02:00:00' DO INSERT INTO mysql.privs_snapshot (host, user, select_priv, insert_priv, grant_priv, ssl_type) SELECT host, user, select_priv, insert_priv, grant_priv, ssl_type FROM mysql.user;
- 事件默认关闭,需先执行
SET GLOBAL event_scheduler = ON; - 注意:事件在
mysql库下创建,但写入目标表必须显式指定库名(如mysql.privs_snapshot),否则可能写到当前默认库
审计时最容易被忽略的三个权限死角
很多团队只查 mysql.user,结果漏掉真实风险点:
-
PROXY权限:可通过SELECT * FROM mysql.proxies_priv;查,允许用户以其他用户身份登录,常被用于绕过审计 - 动态权限(MySQL 8.0+):如
BACKUP_ADMIN、CLONE_ADMIN不出现在mysql.user里,得查mysql.role_edges和mysql.default_roles - 列级权限:存在
mysql.columns_priv表中,GRANT SELECT(col1) ON db.tbl TO 'u'@'%'这类授权不会反映在全局字段里
真正做一次完整审计,至少要覆盖这 5 张表:user、db、tables_priv、columns_priv、procs_priv,且必须在相同事务快照下读取,否则中间权限变更会导致状态不一致。










