用mysqldump --all-databases会跳过information_schema、performance_schema和sys库;需手动查用户库并用--databases导出,加-n -s避免表头误读,权限不足时检查select和lock tables权限,大库备份建议--skip-opt --single-transaction组合。
mysqldump 全库备份命令怎么写才不漏库
直接用 mysqldump --all-databases 看似最省事,但实际会跳过 information_schema、performance_schema 和 sys 这几个系统库——这不是 bug,是默认行为。如果你真需要它们(比如做灾备还原或审计比对),得手动加上 --include-databases 或改用库名列表。
更稳妥的做法是先查出所有用户库,再拼接导出:
mysql -Nse "SELECT SCHEMA_NAME FROM information_schema.SCHEMATA WHERE SCHEMA_NAME NOT IN ('information_schema','performance_schema','sys','mysql')" | xargs mysqldump --databases > full_backup.sql
-
--databases比--all-databases多一层可控性:它会为每个库加CREATE DATABASE和USE语句,还原时不用提前建库 - 务必加
-N(禁用列名)和-s(静默输出),否则xargs会把表头也当库名传进去,报错Unknown database 'SCHEMA_NAME' - 如果库名含短横线或特殊字符,
xargs可能解析失败,这时改用while read循环更稳
遇到 LOCK WAIT TIMEOUT EXCEEDED 就卡住?不是锁问题,是权限不够
执行全库备份时突然停在某个库,日志里反复出现 Lock wait timeout exceeded,第一反应常是“锁表了”,其实大概率是当前账号没权限读取某张表的元数据——特别是用低权限账号(如只给了 SELECT)去 dump 时,mysqldump 内部会查 INFORMATION_SCHEMA.TABLES 等视图,缺 SELECT 权限就卡住等锁超时。
- 检查账号权限:运行
SHOW GRANTS FOR CURRENT_USER(),确认有SELECTon*.*,以及LOCK TABLES(即使没显式加--lock-tables,某些版本也会默认启用) - 临时规避:加
--skip-lock-tables,但要注意这会导致 MyISAM 表可能不一致;InnoDB 表靠--single-transaction更可靠 - 如果必须用最小权限账号,改用
--ignore-table=db1.table1跳过有问题的表,别硬扛
大库备份慢、IO 扛不住?别只盯着压缩,先关掉默认的 --opt
mysqldump 默认开启 --opt(等价于 --add-drop-table --add-locks --create-options --disable-keys --extended-insert --lock-tables),其中 --lock-tables 和 --disable-keys 对大库反而拖慢速度,尤其当单表几千万行时,DISABLE KEYS 本身要遍历索引结构。
- 换成
--skip-opt --single-transaction --routines --triggers --events组合:前者关掉所有默认优化项,后者按需补关键功能 - 导出后用
gzip full_backup.sql.gz比mysqldump ... | gzip > ...更稳定——管道中断会导致整个备份丢失,分两步可校验 SQL 文件完整性 - 如果磁盘 IO 是瓶颈,加
--quick(逐行 fetch,不缓存整结果集),对内存小的机器很关键
还原时提示 ERROR 1044 (42000):Access denied for user,其实是 CREATE DATABASE 权限缺失
用 --databases 或 --all-databases 导出的 SQL 文件开头有 CREATE DATABASE IF NOT EXISTS `xxx`,还原时如果账号没 CREATE 权限,就会在第一行报错退出,而不是继续执行后面的 USE 和建表语句。
- 还原前先确认权限:
GRANT CREATE ON *.* TO 'user'@'host',注意不是CREATE DATABASE(这是旧语法,5.7+ 已弃用) - 不想授全局
CREATE?那就手动删掉 SQL 文件里的所有CREATE DATABASE行,改用mysql -e "CREATE DATABASE IF NOT EXISTS db1"单独建库后再导入 - 如果目标实例已有同名库且结构不同,
IF NOT EXISTS不会覆盖,但后续CREATE TABLE会因表已存在而失败——此时得加--add-drop-table或手动清理
真正麻烦的是跨版本还原:MySQL 8.0 的 CREATE USER 语句带 caching_sha2_password 插件,在 5.7 上直接报错。这种细节不试一次根本想不到。











