应使用 --single-transaction --skip-lock-tables(仅InnoDB有效),MyISAM需停写或--lock-all-tables;调大innodb_lock_wait_timeout;避开高峰,分库/表导出并用--where限行。

mysqldump 导出时如何避免锁表和主从延迟
直接用 mysqldump --all-databases 在生产库上执行,大概率会触发表级锁(尤其 MyISAM)或长事务阻塞(InnoDB 下 --single-transaction 也不总可靠),导致业务写入卡顿甚至主从延迟飙升。
- 优先加
--single-transaction+--skip-lock-tables,但仅对 InnoDB 有效;MyISAM 必须停写或用--lock-all-tables - 导出大表前,确认
innodb_lock_wait_timeout足够长(如 600),否则 dump 过程可能被 kill - 避免在高峰时段全库 dump;可按库/表分批导出,配合
--where="id > 1000000 AND id 分片 - 若主从延迟敏感,导出前先在从库执行
STOP SLAVE;,导出完再START SLAVE;,防止 dump 期间 binlog 积压
跨版本或跨引擎迁移时字段兼容性怎么处理
MySQL 5.7 → 8.0 或 MyISAM → InnoDB 迁移时,mysqldump 默认输出的建表语句可能含不兼容语法(如 8.0 的 utf8mb4_0900_as_cs 排序规则、5.7 不支持的 JSON 列默认值),直接导入会报错。
- 导出时加
--compatible=mysql40或--compatible=ansi可降级语法,但会丢失部分特性(如分区表定义) - 更稳妥的做法:导出后用 sed 或脚本批量替换排序规则,例如把
COLLATE utf8mb4_0900_as_cs替换为COLLATE utf8mb4_unicode_ci - InnoDB 表迁移前检查
ROW_FORMAT:5.7 默认DYNAMIC,但某些老配置下可能是COMPACT,8.0 对后者有警告,建议统一设为DYNAMIC - 含
GENERATED COLUMN或VISIBLE INDEX的表,需确认目标版本是否支持,否则 dump 会失败或导入报错
增量同步用 pt-table-sync 还是基于 binlog 解析
pt-table-sync 适合小规模、低频次校验修复,但无法实时同步;真正做持续数据同步,必须依赖 binlog,否则无法捕获中间变更。
-
pt-table-sync --sync-to-master本质是查主从记录差异再拼 UPDATE/DELETE,网络和锁开销大,线上慎用 - 生产环境推荐
mysqlbinlog+ 自定义解析,或成熟工具如canal、maxwell:它们监听 binlog event,转成结构化消息(JSON/Protobuf),再写入目标库 - 注意
binlog_format必须为ROW,STATEMENT模式下无法精确还原行变更 - 同步程序要处理
GTID断点续传:记录已消费的Executed_Gtid_Set,崩溃重启后从该位置继续拉取
目标库已有数据时如何安全追平而不丢数据
迁移不是“清空再导入”,而是“保留存量 + 合并增量”。常见错误是直接 INSERT IGNORE 或 REPLACE INTO,结果主键冲突时删旧插新,误删业务正在用的记录。
- 用
INSERT ... ON DUPLICATE KEY UPDATE,只更新非主键字段,避免覆盖业务关键状态字段(如status、updated_at) - 对带时间戳的表,加条件判断:例如
ON DUPLICATE KEY UPDATE updated_at = VALUES(updated_at) WHERE VALUES(updated_at) > updated_at,防止旧数据覆盖新数据 - 大表同步前,先在目标库建好唯一索引(含联合唯一),否则
ON DUPLICATE KEY无法生效 - 务必禁用目标库的外键检查:
SET FOREIGN_KEY_CHECKS=0;,否则导入过程可能因外键约束失败
SET FOREIGN_KEY_CHECKS=0; INSERT INTO user (id, name, email, updated_at) SELECT id, name, email, updated_at FROM user_src ON DUPLICATE KEY UPDATE name = VALUES(name), email = VALUES(email), updated_at = CASE WHEN VALUES(updated_at) > updated_at THEN VALUES(updated_at) ELSE updated_at END; SET FOREIGN_KEY_CHECKS=1;
跨库同步最易被忽略的是时区和字符集隐式转换——哪怕源目标都是 utf8mb4,只要 collation_connection 不一致,ORDER BY 或 GROUP BY 就可能出错。迁移前后务必核对 SHOW VARIABLES LIKE '%collation%'; 和 SELECT @@time_zone;。










