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