必须用REVOKE FILE ON . FROM 'user'@'host'精确撤销,同步设置secure_file_priv = NULL并重启,再FLUSH PRIVILEGES、检查角色继承,最后重连验证ERROR 1045或1290。

直接执行 REVOKE FILE ON *.* 语句
FILE 是全局权限,只能在 *.* 作用域撤销,写成 db_name.* 或 mysql.user 都会报错 ERROR 1064(语法错误)。命令必须严格匹配授权粒度:如果当初是用 GRANT FILE ON *.* TO 'backup'@'10.%' 授的权,那就得用 REVOKE FILE ON *.* FROM 'backup'@'10.%' 撤回。
必须同步禁用 secure_file_priv = NULL(8.0.17+)
只撤 FILE 权限还不够。MySQL 8.0.17+ 才支持 secure_file_priv = NULL,这是唯一能让 SELECT INTO OUTFILE 和 LOAD DATA INFILE 直接失败的配置——返回 ERROR 1290,连语句解析都跳过。设为空字符串 '' 或路径(如 /tmp/)仍允许操作,只是受限于目录。
注意:secure_file_priv 是只读变量,不能 SET GLOBAL 动态修改,必须改配置文件:
- 在
[mysqld]段下添加secure_file_priv = NULL - 重启服务:
sudo systemctl restart mysql - 验证:
SELECT @@secure_file_priv;返回值必须是NULL(不是字符串"NULL",也不是空值)
别漏掉角色继承和 FLUSH PRIVILEGES
如果用户属于角色(MySQL 8.0+),REVOKE FILE ON *.* 只影响直接授予的权限,不会自动解除角色绑定。需额外检查:
-
SHOW GRANTS FOR 'user'@'host';看是否含角色名 - 若存在,先
REVOKE 'role_name' FROM 'user'@'host';,再对角色本身也执行REVOKE FILE ON *.* FROM 'role_name'; - 执行完务必
FLUSH PRIVILEGES;,否则权限变更不生效(尤其在修改系统表后)
验证是否真正失效
以该用户登录后执行测试语句,预期结果要明确:
-
SELECT 1 INTO OUTFILE '/tmp/test';→ 必须报 ERROR 1290(说明secure_file_priv = NULL生效)或 ERROR 1045(说明 FILE 权限已撤) - 若返回 ERROR 1045(Access denied),说明权限回收成功;若返回 ERROR 1290,说明配置层已切断能力
- 两者同时满足,才算真正禁用——单独依赖任一手段都有绕过风险
最易被忽略的是:即使权限已撤、配置已设,旧连接仍保有 FILE 能力,必须重连才能验证真实效果。











