mysql数据库的备份策略与异地恢复方案

10次阅读

不是必须,但对InnoDB表强烈建议加–single-transaction;它利用MVCC创建一致性快照、不锁表,仅对InnoDB有效,混用MyISAM仍会全局读锁。

mysql数据库的备份策略与异地恢复方案

mysqldump 备份时必须加 --single-transaction 吗?

不是必须,但对 InnoDB 表强烈建议加。不加会导致备份期间阻塞写入(尤其是 FLUSH TABLES WITH READ LOCK),而 --single-transaction 利用 MVCC 创建一致性快照,全程不锁表。

注意它只对 InnoDB 有效;如果库中混有 MyISAM 表,仍会触发全局读锁。可通过

SELECT ENGINE, COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'your_db' GROUP BY ENGINE;

检查引擎分布。

  • 线上业务库基本都是 InnoDB,--single-transaction 是安全前提
  • 必须搭配 --all-databases--databases 使用,单独指定表时不生效
  • 若备份耗时过长,事务快照可能被 purge 线程清理,导致 Error 1205 (HY000): Deadlock found when trying to get lock —— 此时需调大 innodb_undo_retention

如何用 mysqlbinlog 做基于时间点的异地恢复?

异地恢复依赖完整 binlog + 全量备份。关键不是“能不能”,而是“binlog 是否开启”和“是否保存了从全备时间点起的所有 binlog 文件”。

检查项:SHOW VARIABLES LIKE 'log_bin'; 必须为 ONSHOW VARIABLES LIKE 'expire_logs_days'; 建议设为 7 天以上;SHOW MASTER STATUS; 记下 Fileposition,用于定位起点。

  • 恢复前先停掉目标库的 binlog 写入:SET sql_log_bin = 0;
  • mysqlbinlog --start-datetime="2024-06-01 10:20:00" --stop-datetime="2024-06-01 10:25:00" mysql-bin.000012 | mysql -u root -p 回放指定时间段
  • 若已知误操作语句位置,用 --start-position=12345 --stop-position=12399 更精准,避免跨事务截断
  • 异地恢复时,务必确认源库与目标库的 server_id 不同,否则 GTID 模式下会拒绝执行

异地恢复失败常见报错: ERROR 1840 (HY000): @@GLOBAL.GTID_PURGED can only be set when @@GLOBAL.GTID_EXECUTED is empty

这是 GTID 模式下最典型的初始化冲突。本质是目标实例已执行过其他 GTID 事务,但你要导入的备份里包含 SET @@GLOBAL.GTID_PURGED 语句。

解决路径分两步:先清空目标实例(仅限全新恢复场景),或跳过该语句(生产环境更稳妥)。

  • 全新实例:执行 RESET MASTER; 后再导入 dump 文件
  • 已有数据的实例:用 sed '/GTID_PURGED/d' backup.sql > clean_backup.sql 删除该行,再导入
  • 导入后手动补回 purged 集合:SET GLOBAL GTID_PURGED='xxx-xxx-xxx:1-100';(值来自原备份文件头注释或 SHOW MASTER STATUS
  • 若用 mysqldump --set-gtid-purged=OFF 参数重备,可彻底规避此问题

备份文件传到异地后,mysql 导入慢得离谱?

不是网络或磁盘问题,大概率是默认参数限制。MySQL 客户端在非交互模式下会逐行解析 SQL,遇到大文件极易卡住。

真正有效的提速手段只有三个:

  • 导入前执行 SET FOREIGN_KEY_CHECKS=0; SET UNIQUE_CHECKS=0; SET AUTOCOMMIT=0;,导入末尾再恢复
  • mysql --max-allowed-packet=512M -u root -p 显式调大包大小,避免因单条 INSERT 超长被截断重试
  • 若备份含大量 INSERT INTO ... VALUES (...),(...),(...),确保 mysqld 的 bulk_insert_buffer_size 足够(建议 ≥ 64M)

异地恢复的核心从来不是“怎么拷贝”,而是“怎么让目标实例信任并正确解释你传过去的那 SQL 和 binlog”。GTID、server_id、字符集、SQL_MODE 这些看似配置项的东西,任何一个不一致,都会在最后一刻报出完全不相关的错误。

text=ZqhQzanResources