4.5 KiB
4.5 KiB
name, description, status, version, date
| name | description | status | version | date |
|---|---|---|---|---|
| mysql-schema-sync | MySQL 表结构同步最佳实践:跨环境同步 DDL,处理 CREATE/ALTER 失败场景 | proposal | v1 | 2026-08-14T07:14:36.432Z |
MySQL 表结构同步最佳实践
场景
将准生产/测试环境的表结构同步到 VPS/生产环境,确保 DDL 一致。
核心原则
- 表名必须带数据库前缀 - 如
dmp_smdm.dmp_md_item_info,因为生产实例有多个库 - 不暴露敏感信息 - 脚本中只写库名和表名,IP/密码用环境变量
- 先验证后执行 - 先 SELECT 确认表结构和数据量
- CREATE 优先于 ALTER - 能新建不修改,减少冲突
脚本生成规范
1. 使用 mysqldump 导出结构
# 导出单个库的所有表结构(无数据)
mysqldump -h SOURCE_HOST -P PORT -u USER -p"PASSWORD" \
--no-data --skip-lock-tables \
DB_NAME > db_struct.sql
2. 脚本格式要求
-- ============================================================
-- 表结构同步脚本:table_name
-- 源:准生产 (host:port)
-- 目标:VPS (host:port) database
-- 生成时间:YYYY-MM-DD HH:MM:SS
-- ============================================================
-- 表:database.table_name
CREATE TABLE IF NOT EXISTS `database`.`table_name` (
-- 字段定义
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='表说明';
-- 验证
-- SHOW CREATE TABLE database.table_name\G
3. 目录结构
xuan-sql/scripts/YYYYMMDD/
├── README.md # 同步记录(成功/失败清单)
├── database__table__struct.sql # 单表脚本
└── run_sync.sh # 批量执行脚本
执行策略
CREATE TABLE(新建表)
✅ 成功率高,直接使用 CREATE TABLE IF NOT EXISTS
for sql_file in database__*_struct.sql; do
mysql -h TARGET_HOST -u root -p"PASSWORD" -D database < "$sql_file"
done
ALTER TABLE(修改表)
⚠️ 失败率高,需要特殊处理:
-
先检查目标表是否存在
SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'database' AND TABLE_NAME = 'table_name'; -
对比结构差异
-- 源表结构 SHOW CREATE TABLE source.table_name\G -- 目标表结构 SHOW CREATE TABLE target.table_name\G -
生成差异脚本(只修改不同的字段/索引)
-
外键约束延迟添加
- 先执行字段/索引变更
- 所有表完成后,再添加外键
常见失败原因及处理
| 错误类型 | 原因 | 解决方案 |
|---|---|---|
| 字段已存在 | 目标表已有同名字段 | 跳过或使用 ALTER TABLE ... MODIFY COLUMN |
| 索引冲突 | 同名的索引已存在 | 先 DROP INDEX 再 ADD INDEX |
| 外键约束失败 | 引用的表/字段不存在 | 延迟到所有表创建后添加外键 |
| 字符集冲突 | 现有数据与新字符集不兼容 | 保持原字符集或先转换数据 |
| NOT NULL 约束 | 字段有 NULL 值但改为 NOT NULL | 先更新 NULL 值为默认值 |
验证步骤
-
表数量对比
SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'database'; -
结构对比
SHOW CREATE TABLE database.table_name\G -
关键字段验证
SELECT COLUMN_NAME, IS_NULLABLE, COLUMN_DEFAULT, DATA_TYPE FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = 'database' AND TABLE_NAME = 'table_name';
回滚方案
-
执行前备份
mysqldump -h TARGET_HOST -u root -p"PASSWORD" \ --no-data --routines --triggers \ database > backup_before_sync.sql -
记录执行日志
./run_sync.sh > sync_log.txt 2>&1 -
失败表单独处理
- 记录失败的表和错误信息
- 人工分析后生成修复脚本
示例:dmp_smdm 同步(2026-08-14)
源: 准生产 100.115.195.188:50036
目标: VPS 101.34.227.188:3306
| 统计 | 数量 |
|---|---|
| 总表数 | 127 |
| CREATE 成功 | 93 ✅ |
| ALTER 失败 | 34 ❌ |
失败表特征: 全部是 ALTER TABLE 操作的核心业务表(客户、物料、BOM、工艺路线等)
后续处理:
- 人工对比失败表的源/目标结构差异
- 生成针对性的 ALTER 脚本(只修改必要字段)
- 在业务低峰期执行变更
相关技能
- sql-toolkit: SQL 查询、设计、迁移
- mysql-ddl-backup: 定时备份表结构