mysqldump全量备份导致CPU和IO突增,应加--single-transaction(InnoDB)、ionice或pv限流、避开高峰;增量用mysqlbinlog按时间或position解析ROW格式binlog;多线程同步需按库分发并禁用外键检查;续传推荐GTID或持久化position。

mysqldump 做全量备份时 CPU 和 IO 突增怎么办
直接用 mysqldump 拉全库,尤其在业务高峰期,会抢光磁盘 IO 和 CPU 资源,导致主库响应变慢甚至超时。它默认单线程、全表锁(对 MyISAM)或长事务(对 InnoDB),不是“安静干活”的类型。
- 加
--single-transaction(仅 InnoDB)避免锁表,但会拉长事务视图,可能拖慢其他长查询 - 用
--skip-lock-tables配合--single-transaction,别单独用——否则可能丢数据 - 限制 IO:Linux 下用
ionice -c2 -n7降级调度优先级,或pv -L 20m控制输出流速(需管道接入) - 避开高峰:全量备份尽量选凌晨低峰,且提前确认 binlog 位置(
SHOW MASTER STATUS),为后续增量对齐打基础
如何从 binlog 拉出指定时间段的增量 SQL
靠 mysqlbinlog 解析,不是“导出就完事”,时间点、GTID、格式三者不匹配就会跳过或报错。
- 先确认 binlog 格式是
ROW(SELECT @@binlog_format),STATEMENT模式下部分语句无法精确重放 - 用
--start-datetime和--stop-datetime最直观,但注意时区——必须和 MySQL 服务器时区一致(查SELECT @@system_time_zone) - 更稳的方式是用
--start-position/--stop-position,位置号来自SHOW BINLOG EVENTS或上一次全量备份记录的Position - 加上
--base64-output=DECODE-ROWS -v可读性高,但体积大;线上用建议去掉-v,只保留--base64-output=DECODE-ROWS防乱码
多线程同步时为什么数据会乱序或重复
MySQL 原生不支持多线程回放 binlog,所谓“多线程同步”本质是分库/分表后并行导入,一旦跨表关联或存在外键约束,顺序一乱,INSERT 就失败或数据错位。
- 按库拆分最安全:
mysqlbinlog ... | grep "^USE `db1`" -A 1000 | mysql -u... db1这类手动切分要谨慎,grep 容易截断语句 - 推荐用
mydumper+myloader:它按表导出,myloader -t 4启 4 线程导入,且自动处理建表顺序和外键禁用 - 别对单表开多线程——即使表很大,
myloader对单表仍是串行执行,强行拆分 insert 会导致主键冲突或唯一键报错 - 所有线程共用同一个目标库时,务必在导入前执行
SET FOREIGN_KEY_CHECKS=0和SET UNIQUE_CHECKS=0,导入完成再恢复
增量同步中断后怎么续传不丢不重
靠人工记 position 或 datetime 续传极不可靠,错一位、差一秒,轻则漏数据,重则主从不一致。真正能落地的是用 GTID + mysqlbinlog --exclude-gtids 或专用工具状态追踪。
- 如果开了 GTID(
gtid_mode=ON),用mysqlbinlog --exclude-gtids="aaa-bbb-ccc:1-100"跳过已处理事务,比位置更鲁棒 - 但注意:GTID 不跨集群复制,若迁移目标是新实例且未开启 GTID,就别依赖它——得老实用 position
- 每次增量同步完成后,把最新 position 写入一个独立小表(如
meta.sync_position)或本地文件,下次启动前读取,而不是靠日志里找最后一行 - 不要用
mysqlbinlog --to-last-log直接追到末尾——万一 binlog 切了,它会报错退出,必须配合--read-from-remote-server动态连接读取
真正麻烦的不是命令怎么写,而是全量和增量之间那个“时间窗口”怎么卡准:备份结束时刻的 binlog position 必须和第一个增量起始点严丝合缝,差一条,就可能丢用户刚提交的订单。



















