最稳妥的同步结构方式是用 SHOW CREATE TABLE 获取建表语句并手动删除 AUTO_INCREMENT=xxx 及其后逗号,避免 mysqldump --no-data 导出时残留该参数导致主键冲突;同时须核对 sql_mode 和 lower_case_table_names 配置差异。
同步结构时怎么跳过 AUTO_INCREMENT 值
直接用 mysqldump --no-data 导出再改 sql 是最稳妥的,但容易漏掉表选项。关键不是“跳过自增”,而是“不带自增值重建表”——create table 语句里删掉 auto_increment=12345 这种显式赋值即可。
常见错误现象:mysqldump --skip-triggers --no-data 导出后,CREATE TABLE 里仍含 AUTO_INCREMENT=xxx,导致生产库建表失败或主键冲突。
- 用
sed '/AUTO_INCREMENT=/d'或perl -pi -e 's/AUTO_INCREMENT=[0-9]+//g'清洗 dump 文件(注意别误删列定义里的数字) - 更安全的做法:用
SHOW CREATE TABLE拿建表语句,手动删掉AUTO_INCREMENT和后面逗号(如ENGINE=InnoDB AUTO_INCREMENT=12345 DEFAULT CHARSET=utf8mb4→ENGINE=InnoDB DEFAULT CHARSET=utf8mb4) - MySQL 8.0+ 可配合
information_schema.TABLES批量查出所有带自增的表,避免漏表
测试库改结构后怎么无损推到生产库
核心原则:不锁表、不中断写入、不依赖业务停机窗口。重点不是“同步”,而是“渐进式变更”。pt-online-schema-change 是目前最成熟的方案,但得确认它是否支持你的 MySQL 版本和存储引擎。
使用场景:加字段、改字段类型(非严格)、加索引、删索引。不支持修改主键、分区变更、全文索引等高危操作。
- 必须提前在从库验证
pt-osc脚本能否跑通,尤其注意触发器权限(TRIGGER权限 +SELECT/INSERT/UPDATE/DELETE) - 执行前检查
innodb_lock_wait_timeout是否足够长(建议 ≥ 120),否则大表可能中途失败并残留 _old 表 - 如果表有外键,
--alter-foreign-keys-method=auto会自动处理,但需确保引用表没被同时修改,否则可能死锁
ALTER TABLE ... ALGORITHM=INSTANT 真的能无损吗
只对极少数操作有效:加/删虚拟列、重命名列、修改列注释、加/删二级索引(MySQL 8.0.12+)。其他操作哪怕加个 NOT NULL 都会退化成 COPY,锁表时间取决于数据量。
性能影响:INSTANT 不读数据页,几乎不耗 I/O;但 COPY 模式下,大表可能卡住写入数分钟甚至小时,且临时磁盘空间要 ≥ 原表大小。
- 用
SHOW CREATE TABLE查看当前表的ROW_FORMAT,COMPACT或REDUNDANT格式不支持 INSTANT,必须先ALTER TABLE ... ROW_FORMAT=DYNAMIC - 执行前务必
EXPLAIN FORMAT=TREE ALTER TABLE ...(MySQL 8.0.16+),看实际选的 algorithm 是什么 - 即使显示 INSTANT,也要在测试库压测验证:某些云厂商 RDS 对 INSTANT 有额外限制(比如阿里云 PolarDB 早期版本禁用部分 INSTANT 场景)
为什么不能直接 mysqldump --no-data + mysql 导入生产库
因为 mysqldump 默认导出的 CREATE TABLE 包含 ENGINE、CHARSET、COLLATION、ROW_FORMAT 等细节,而测试库和生产库的 MySQL 配置往往不同,比如 sql_mode 差异会导致 STRICT_TRANS_TABLES 下建表失败。
错误现象示例:ERROR 1067 (42000): Invalid default value for 'created_at',本质是测试库关了严格模式,导出的 created_at DATETIME DEFAULT '0000-00-00 00:00:00' 在生产库报错。
- 导出时加
--compatible=mysql40或--skip-create-options(慎用,会丢引擎信息) - 更推荐方式:用
SELECT CONCAT('ALTER TABLE `', table_name, '` ', ...)构造最小化变更语句,只动真正需要改的部分 - 所有结构变更脚本必须在生产库低峰期执行,并配好回滚语句(比如改字段前先
CREATE TABLE t_bak AS SELECT * FROM t)
事情说清了就结束。最常被忽略的是:没人检查 sql_mode 和 lower_case_table_names 的差异,这两个配置一不一致,mysqldump 出来的语句在生产库上十有八九会报错。

















