必须加--single-transaction,否则InnoDB表备份时可能因并发写入导致数据不一致;它通过MVCC创建一致性快照实现无锁备份,但仅对InnoDB有效,MyISAM仍会锁表,且不能与--lock-all-tables共用。

mysqldump 备份时加 --single-transaction 为什么必须?
不加 --single-transaction,InnoDB 表在备份过程中可能被其他事务修改,导致导出的 SQL 文件数据不一致——比如某张订单表里部分记录是“已支付”,另一部分却是“待支付”,而实际业务中这两条本应同时存在或同时不存在。
这个参数只对 InnoDB 有效,它会启动一个一致性快照(基于 MVCC),整个备份过程像“定格”一样读取数据,无需锁表。但注意:--single-transaction 不能保证 MyISAM 表一致性,这类表仍会被锁定。
- 必须搭配
--databases或指定库名使用,否则可能漏掉 CREATE DATABASE 语句 - 如果备份期间有 DDL 操作(如 ALTER TABLE),快照可能失效,报错
ERROR 1182 (HY000): Got error 154 'Table definition has changed, please retry transaction' - 不要和
--lock-all-tables同时用,二者冲突
还原大 SQL 文件时卡住或失败怎么办?
直接执行 mysql -u root -p db_name 在遇到几百 MB 以上的文件时,常因超时、内存不足或 max_allowed_packet 限制中断,错误信息通常是:<code>Lost connection to MySQL server during query 或 Packets larger than max_allowed_packet are not allowed。
解决核心是绕过客户端限制,改用服务端加载方式:
- 先登录 MySQL:
mysql -u root -p,再执行use db_name;,然后用source /path/to/backup.sql;—— 这样走的是服务端解析路径,不受 client 端 packet 限制 - 临时调大服务端参数:
SET GLOBAL max_allowed_packet = 1073741824;(1GB),再 source;记得还原后恢复原值 - 若文件含大量 INSERT,可提前关掉 autocommit:
SET autocommit=0;,最后手动COMMIT;,大幅提升导入速度
物理备份 xtrabackup 恢复失败常见原因
xtrabackup --copy-back 报错 Failed to create a directory: /var/lib/mysql/xxx: Permission denied 或启动失败提示 InnoDB: Unable to lock ./ibdata1 error,基本不是命令写错,而是权限或状态没清理干净。
关键点在于:xtrabackup 恢复的是原始二进制文件,它不关心 MySQL 是否运行,但要求目标目录干净、权限正确、且 MySQL 完全停止。
- 必须先
systemctl stop mysqld,不能只 kill 进程,否则 ib_logfile* 可能残留锁 - 恢复前清空
/var/lib/mysql(保留mysql.sock不删,但目录内其他全删),否则文件冲突 - 复制完必须执行
chown -R mysql:mysql /var/lib/mysql,否则 mysqld 启动时拒绝读取数据文件 -
--prepare步骤不可跳过,尤其是增量备份合并后,没 apply redo 日志会导致崩溃
增量备份依赖 binlog,但恢复时找不到日志文件
用 mysqlbinlog 回放时提示 Could not open log file,往往不是路径错了,而是 binlog 被自动清理了——expire_logs_days 默认是 0(永不过期),但很多运维会设成 7 或 30,一旦全量备份间隔超过该值,中间 binlog 就没了。
真正可靠的做法是:每次全量备份后,立刻 FLUSH LOGS,然后手动归档当前 binlog,并记录 SHOW MASTER STATUS 输出的 File 和 Position 值,作为下一次增量起点。
- 归档命令示例:
cp /var/lib/mysql/mysql-bin.000001 /backup/binlog/,然后mysql -e "PURGE BINARY LOGS TO 'mysql-bin.000002';" - 回放时别只靠文件名排序,要用
mysqlbinlog --start-position=12345 /backup/binlog/mysql-bin.000001 | mysql -u root -p - 生产环境建议把 binlog 存到 NFS 或对象存储,避免单点丢失
备份本身不难,难的是让每次还原都能成功。最常被忽略的不是命令怎么写,而是备份时刻的状态是否可控、还原路径是否被验证过、以及 binlog 归档是否真落地了——这些环节一断,再漂亮的备份脚本也救不了数据。


















