备份用户只需要 SELECT + LOCK TABLES + RELOAD(非必需但推荐)
MySQL 备份用户(如用
mysqldump做逻辑备份)**不需任何写权限,也不该有**。最小可行权限组合是:
SELECT(读数据)、
LOCK TABLES(保证一致性快照)、
SHOW VIEW(若库中有视图)、
TRIGGER(若表带触发器且需导出定义)。
RELOAD权限仅在启用
--single-transaction时非必须,但加了更稳妥——它允许执行
FLUSH TABLES WITH READ LOCK回退方案。
SELECT:必须,读取所有待备份表的数据
LOCK TABLES:必须,
mysqldump默认会尝试加表级读锁;没这权限会报错
Access denied; you need (at least one of) the LOCK TABLES privilege(s) for this operation
SHOW VIEW:必须,否则视图会被跳过或报错
Access denied for view ...
TRIGGER:建议加上,否则
mysqldump --triggers(默认开启)会失败
RELOAD:非强制但强烈建议,让
mysqldump在无法用事务快照时能降级使用全局只读锁
CREATE USER 'bkp_user'@'localhost' IDENTIFIED BY 'strong_pass_2025'; GRANT SELECT, LOCK TABLES, SHOW VIEW, TRIGGER ON myapp_db.* TO 'bkp_user'@'localhost'; GRANT RELOAD ON *.* TO 'bkp_user'@'localhost'; -- 注意:RELOAD 是全局权限,必须写 *.* FLUSH PRIVILEGES;
别给 backup 用户 PROCESS 或 SUPER 权限
有些文档误写“加
PROCESS才能看线程”,其实
mysqldump完全不需要它;而
SUPER更是高危权限,一旦泄露可执行
KILL、修改系统变量、甚至绕过认证。真实错误现象包括: 给了
PROCESS后,
mysqldump确实不报错,但这是过度授权——它只是恰好没被拒绝,不是真需要 给了
SUPER,用户能执行
SET GLOBAL read_only=OFF,瞬间让只读备份账号获得写能力 某些云数据库(如阿里云 RDS、腾讯云 CDB)直接禁用
SUPER和
PROCESS,强行加会导致
GRANT报错
跨库备份?按需授权,绝不写 *.*
如果备份脚本要 dump 多个库(比如
myapp_db和
log_db),常见错误是直接授
SELECT ON *.*—— 这违反最小权限,且可能意外暴露系统库(如
mysql、
information_schema)。 正确做法:显式列出每个业务库,分别授权
GRANT SELECT, LOCK TABLES, SHOW VIEW, TRIGGER ON myapp_db.* TO 'bkp_user'@'localhost';
GRANT SELECT, LOCK TABLES, SHOW VIEW, TRIGGER ON log_db.* TO 'bkp_user'@'localhost';禁止对
mysql、
performance_schema、
sys授权,这些库含敏感元数据 若用
mysqldump --all-databases,必须确认是否真需要全部——生产环境几乎从不这么做
验证权限是否真生效?用 SHOW GRANTS
+ 实际跑一次 dump
授完权别只信
GRANT语句成功就完事。真实权限可能因 host 匹配顺序、缓存未刷新、或权限表冲突而失效。 先查:运行
SHOW GRANTS FOR 'bkp_user'@'localhost';,确认输出中每条
GRANT都是你预期的,没有多余项 再试:用该用户实际执行一次最小化 dump:
mysqldump -ubkp_user -p -h127.0.0.1 --single-transaction --databases myapp_db > /tmp/test.sql常见漏掉的坑:
bkp_user创建时指定的是
'bkp_user'@'%',但你连的是
localhost——MySQL 会匹配
'bkp_user'@'localhost'(更高优先级),而这个账户可能根本没建或没授权
最小权限不是设一次就完事的事。备份用户权限要随业务库增减同步调整,每次上线新表、新视图、新触发器,都得回头检查
SHOW GRANTS输出是否仍覆盖全部对象——否则 dump 会静默跳过某些表,你以为备全了,其实早丢数据了。
