mysqldump报Access denied主因是权限缺失而非密码错误,必须授予SELECT、LOCK TABLES、SHOW VIEW、TRIGGER四类最小权限,全局PROCESS权限用于--single-transaction,且必须执行FLUSH PRIVILEGES生效。

mysqldump 报 Access denied,90% 不是密码错,而是权限没给够——而且不是“少给一点”,是缺了 SELECT、LOCK TABLES、SHOW VIEW、TRIGGER 这四类基础权限中的任意一个,就必然失败。
哪些权限是 mysqldump 必须的?
mysqldump 不只是读数据,它要查元数据、锁表、解析视图定义、抓触发器 SQL。哪怕你用该账号能正常 SELECT * FROM t1,也不代表能跑通备份。
-
SELECT:读取所有表数据(必须) -
LOCK TABLES:保证一致性导出(加--lock-tables或默认行为下必需) -
SHOW VIEW:库中存在视图时必加,否则跳过或报错 -
TRIGGER:表有触发器时必加,否则导出的CREATE TABLE里不带触发器定义
别用 GRANT ALL PRIVILEGES ON *.* ——这是高危操作。应限定到具体库,例如:
GRANT SELECT, LOCK TABLES, SHOW VIEW, TRIGGER ON `app_db`.* TO 'backup_user'@'localhost';
授完权后必须执行 FLUSH PRIVILEGES;,否则不生效。
安装、修复、更新或打包一个基于 Python 和 PyMySQL 实现的 Windows `mysql` 命令。适用于用户希望在 PowerShell/CMD 中输入 `mysql` 时重定向到 Python 实现、需要交互式输入 MySQL 连接信息、需要同步到当前用户本地 bin 目录,或需要将该能力封装成可公开复用的 Codex skill。
为什么加了 --single-transaction 还报 PROCESS 权限不足?
mysqldump --single-transaction 默认会尝试读取 INFORMATION_SCHEMA.INNODB_TRX 等系统表,这就需要全局 PROCESS 权限。它和前面四类不同:不能按库授予,只能全局给。
- 典型触发场景:
--all-databases、未加--no-tablespaces、用的是 Percona/GreatSQL 等启用了表空间管理的分支 - 解决方法(root 执行):
GRANT PROCESS ON *.* TO 'backup_user'@'localhost'; FLUSH PRIVILEGES; - 若安全策略严禁全局权限,可用
--no-tablespaces绕过,但需确认目标库是否依赖.ibd表空间独立存储
备份文件为空或只有 CREATE DATABASE?先排查连接与识别问题
这不是权限问题,而是 mysqldump 根本没连上目标库,或压根没识别到你要导的库名。
- 检查数据库名拼写是否完全一致(Linux 下区分大小写):
mysqldump -u user -p app_db中的app_db必须真实存在且用户有访问权限 - Docker、多实例或 socket 异常时,
localhost可能走 Unix socket 而非 TCP,加-h 127.0.0.1强制走网络连接 - 加
--verbose看实时输出:mysqldump --verbose -u user -p app_db 2>&1 | grep -E "(Connecting|Dumping|Warning)"
容易被忽略的兼容性陷阱:sql_mode 和外键
备份时没问题,还原时报 Incorrect date value: '0000-00-00' 或外键冲突?大概率是源库和目标库 sql_mode 不一致,或没关外键检查。
-
mysqldump默认会在 dump 文件开头插入SET FOREIGN_KEY_CHECKS=0;和SET SQL_MODE=...,但如果你用了--compact,这些语句会被删掉 - 生产环境建议显式加参数:
--no-tablespaces --skip-triggers --set-gtid-purged=OFF(如不需要 GTID),并确认两端sql_mode至少都包含NO_ZERO_DATE - 还原前手动执行
SET FOREIGN_KEY_CHECKS=0;是常见兜底做法,但不如在 dump 时确保语句完整
真正难搞的从来不是“怎么加权限”,而是权限给了之后,mysqldump 在不同 MySQL 版本、不同分支、不同 sql_mode 下悄悄绕过你设的边界——所以每次换环境,都要用 --verbose 看一眼它到底连了谁、读了啥、跳过了什么。

















