php如何同步两个数据库_数据迁移的实用操作【汇总】

3次阅读

最稳的起点是mysqldump+mysql一次性全量同步;需分批事务导入、处理主键冲突、记录断点、校验auto_increment和timestamp一致性,并用show create table比对建表语句。

php如何同步两个数据库_数据迁移的实用操作【汇总】

mysqldump + mysql 做一次性全量同步

直接导出再导入是最稳的起点,适合首次迁移或数据量不大(

  • mysqldump 默认不导出 CREATE DATABASE 语句,目标库得提前建好,且字符集要和源库一致(比如都用 utf8mb4),否则中文变问号
  • --single-transaction 可避免锁表,但只对 InnoDB 有效;MyISAM 必须用 --lock-all-tables,会阻塞写入
  • 别漏掉 --routines(存储过程)、--triggers(触发器),否则业务逻辑可能断掉
  • 示例命令:mysqldump -h src_host -u user -p --single-transaction --routines --triggers db_name | mysql -h dst_host -u user -p db_name

pt-table-sync 做增量比对与修复

当两个库已运行一段时间、需要校验并修复差异时,pt-table-sync 是目前最可靠的工具。它不依赖 binlog,而是逐行比对主键或唯一索引,适合跨机房、跨版本场景。

  • 必须确保两张表结构完全一致(包括索引、自增起始值),否则会跳过或报错 Cannot find a unique index
  • 默认只输出 SQL,加 --execute 才真正执行修复,建议先用 --print 看一遍要改什么
  • 如果主从延迟大,或者目标库有活跃写入,--sync-to-master 模式可能误删数据,优先选 --replicate 模式(需提前建好校验表)
  • 性能上,单表超千万行时建议加 --chunk-size 控制每次比对量,避免内存爆掉

php 脚本做条件性同步(比如只同步某段时间订单)

纯 PHP 写同步逻辑,灵活性最高,但也最容易出错——尤其是事务边界和错误恢复。别把它当成“简单循环插入”,本质是分布式状态同步。

  • 源库查数据必须用游标分页(WHERE id > ? ORDER BY id LIMIT ?),不用 OFFSET,否则越往后越慢还丢数据
  • 目标库写入必须包在事务里,且每批(比如 100 条)提交一次,不然内存撑爆或锁表太久;但也要防事务太大导致 innodb_log_file_size 不够
  • 记得处理 ON DUPLICATE KEY UPDATEINSERT ... ON CONFLICTpostgresql),否则主键冲突直接中断
  • 一定要记录最后同步的 idupdated_at 到独立配置表或文件,断点续传不能靠“上次脚本结束时间”这种模糊值

忽略 auto_incrementtimestamp 导致的隐性不一致

这是线上最常被忽略的坑:两个库看着数据一样,但新插入记录的 idcreated_at 行为不一致,后续关联查询或分页就出问题。

立即学习PHP免费学习笔记(深入)”;

  • mysqldump 默认导出会带 SET INSERT_METHOD=NOSET TIMESTAMP=...,但如果你手动拼 SQL 或用 ORM 同步,这些元信息就丢了
  • 目标库的 auto_increment_offsetauto_increment_increment 如果和源库不同,即使数据一样,下一条自增 ID 也会错位
  • TIMESTAMP 字段在插入 NULL 时会自动设为当前时间,但时区设置(time_zone)不同会导致值差几小时,务必检查 select @@time_zone
  • SHOW CREATE TABLE 对比两边建表语句,重点关注 AUTO_INCREMENT 值、default 表达式、ON UPDATE CURRENT_TIMESTAMP 是否一致

同步这事,难点不在“怎么把数据搬过去”,而在于“怎么确认搬过去的就是对的”——尤其当表有触发器、外键、生成列或 json 字段时,光看行数和主键匹配远远不够。

text=ZqhQzanResources