mcpField
M
migration-planner

migration-planner

github.com/patricio0312rev数据与数据库63267 次安装41 周前更新
代码仓库

关于 migration-planner

帮助负责生产环境迁移的团队规划低停机迁移。它组织分阶段发布、数据验证、风险控制和回滚方案。

主要功能

  1. 01功能标记与蓝绿部署模式
  2. 02双写和回填规划
  3. 03数据验证策略
  4. 04各阶段回滚方案
  5. 05风险与沟通规划

适用场景

  1. 01规划数据库迁移
  2. 02逐步切换读取流量
  3. 03准备验证和回滚步骤

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/patricio0312rev/skills --skill migration-planner

安装后在 Claude Code 中输入/migration-planner确认已加载。

详细介绍

迁移规划器

执行安全、零停机的迁移,并制定验证和回滚计划。

迁移模式

1. 功能标记迁移(最安全)
Phase 1: Deploy new code (disabled)
Phase 2: Enable for 1% traffic
Phase 3: Ramp to 10%, 50%, 100%
Phase 4: Remove old code
2. 双写迁移
Phase 1: Write to both old and new
Phase 2: Backfill old → new
Phase 3: Read from new (write both)
Phase 4: Stop writing to old
Phase 5: Decommission old
3. 蓝绿部署
Blue (current) → Green (new)
Switch traffic: Blue → Green
Rollback available: Green → Blue

完整迁移计划模板

# Migration Plan: MySQL → PostgreSQL

## Overview

**What:** Migrate user database from MySQL to PostgreSQL
**Why:** Better JSON support, improved performance
**When:** Q1 2024
**Owner:** Database Team
**Risk Level:** HIGH

## Current State

- MySQL 8.0
- 500GB data
- 100K users
- 1000 writes/min
- 10,000 reads/min

## Target State

- PostgreSQL 15
- Same data model
- No downtime
- Data validation 100% match

## Phases

### Phase 1: Dual Write (Week 1-2)

**Goal:** Write to both databases

**Steps:**

1. Deploy PostgreSQL cluster
2. Create schema in PostgreSQL
3. Deploy dual-write code
4. Enable dual writes (MySQL primary, PostgreSQL secondary)

**Code:**

```typescript
async function createUser(data: CreateUserDto) {
  // Write to MySQL (primary)
  const mysqlUser = await mysql.users.create(data);

  // Write to PostgreSQL (secondary, fire and forget)
  postgres.users.create(data).catch((err) => {
    logger.error("PostgreSQL write failed", err);
  });

  return mysqlUser; // Still trust MySQL
}
```

验证:

  • 监控 PostgreSQL 写入成功率
  • 每日比较行数
  • 如果数据偏差 >0.1%,则发出警报

回滚: 禁用 PostgreSQL 写入

阶段 2:回填(第 3-4 周)

目标: 复制历史数据

步骤:

  1. 创建 MySQL 快照
  2. 分批运行回填脚本
  3. 验证数据完整性
  4. 失败后自动恢复

脚本:

def backfill():
    last_id = get_last_migrated_id()
    batch_size = 1000

    while True:
        users = mysql.query(
            "SELECT * FROM users WHERE id > %s LIMIT %s",
            [last_id, batch_size]
        )

        if not users:
            break

        postgres.bulk_insert(users)
        last_id = users[-1]['id']
        save_checkpoint(last_id)

        time.sleep(0.1)  # Rate limit

验证:

  • 行数匹配
  • 随机抽样比较(1000 行)
  • 校验和比较

回滚: 删除 PostgreSQL 数据

阶段 3:双读(第 5 周)

目标: 验证 PostgreSQL 读取

步骤:

  1. 部署影子读取代码
  2. 从两边读取(MySQL 为主)
  3. 比较结果
  4. 记录不匹配项

代码:

async function getUser(id: string) {
  const mysqlUser = await mysql.users.findById(id);

  // Shadow read from PostgreSQL
  postgres.users.findById(id).then((pgUser) => {
    if (!deepEqual(mysqlUser, pgUser)) {
      logger.warn("Data mismatch", { id, mysqlUser, pgUser });
      metrics.increment("migration.mismatch");
    }
  });

  return mysqlUser; // Still trust MySQL
}

验证:

  • 不匹配率 <0.01%
  • PostgreSQL 查询性能可接受

回滚: 移除影子读取

阶段 4:切换读取流量(第 6 周)

目标: 从 PostgreSQL 读取

步骤:

  1. 功能标记:从 PostgreSQL 读取(1% 流量)
  2. 监控错误和延迟
  3. 逐步增加:1% → 10% → 50% → 100%
  4. 继续写入两边

代码:

async function getUser(id: string) {
  if (featureFlags.readFromPostgres) {
    return postgres.users.findById(id);
  }
  return mysql.users.findById(id);
}

验证:

  • 错误率没有变化
  • 延迟 p95 <500ms
  • 没有用户投诉

回滚: 关闭功能标记

阶段 5:停止 MySQL 写入(第 7 周)

目标: PostgreSQL 现在作为主数据库

步骤:

  1. 停止写入 MySQL
  2. 保持 MySQL 运行(只读)
  3. 监控问题

代码:

async function createUser(data: CreateUserDto) {
  return postgres.users.create(data);
  // No longer writing to MySQL
}

验证:

  • 所有操作正常运行
  • MySQL 未收到写入

回滚: 重新启用 MySQL 写入

阶段 6:停用(第 8 周)

目标: 移除 MySQL

步骤:

  1. 归档 MySQL 数据
  2. 关闭 MySQL 集群
  3. 移除 MySQL 客户端代码

回滚: 不可用(不可逆点)

验证策略

数据完整性检查
def validate_migration():
    # Row counts
    mysql_count = mysql.query("SELECT COUNT(*) FROM users")[0]
    pg_count = postgres.query("SELECT COUNT(*) FROM users")[0]
    assert mysql_count == pg_count

    # Random sampling
    sample = mysql.query("SELECT * FROM users ORDER BY RAND() LIMIT 1000")
    for row in sample:
        pg_row = postgres.query("SELECT * FROM users WHERE id = %s", [row['id']])
        assert row == pg_row

    # Checksums
    mysql_checksum = mysql.query("SELECT MD5(GROUP_CONCAT(id, email)) FROM users")
    pg_checksum = postgres.query("SELECT MD5(STRING_AGG(id::text || email, '')) FROM users")
    assert mysql_checksum == pg_checksum

回滚计划

阶段 1-3 回滚(简单)
  • 禁用 PostgreSQL 写入
  • 不影响用户
  • MySQL 中的数据仍然有效
阶段 4 回滚(中等)
  • 切换功能标记
  • 将读取路由回 MySQL
  • 对用户的影响很小(几秒钟)
阶段 5+ 回滚(困难)
  • 必须重新启用 MySQL 写入
  • 可能丢失数据(阶段 5 之后的写入)
  • 需要恢复双写

风险缓解

风险 1:数据丢失

缓解措施:

  • 验证完成前保持双写
  • 捕获事务日志
  • 持续备份
风险 2:性能下降

缓解措施:

  • 对 PostgreSQL 进行负载测试
  • 优化查询
  • 使用连接池
风险 3:架构差异

缓解措施:

  • 架构验证脚本
  • 在预发布环境中测试迁移
  • 记录数据类型差异

沟通计划

利益相关方更新
**Week 0:** Migration announced
**Week 2:** Phase 1 complete (dual writes)
**Week 4:** Backfill complete
**Week 6:** Traffic shifted to PostgreSQL
**Week 8:** Migration complete
状态仪表板
  • 当前阶段
  • 数据同步状态(%)
  • 验证结果
  • 错误率

测试计划

迁移前测试
  1. 在开发环境中测试
  2. 在预发布环境中进行完整迁移
  3. 对 PostgreSQL 进行负载测试
  4. 验证回滚流程
迁移期间
  1. 持续监控
  2. 自动验证
  3. 手动抽查
  4. 用户验收测试

最佳实践

  1. 小批次:逐步迁移
  2. 双写:保持两个系统同步
  3. 功能标记:控制发布
  4. 持续验证:不要轻信,务必验证
  5. 做好回滚准备:为最坏情况做好计划
  6. 密切监控:跟踪指标
  7. 经常沟通:及时告知利益相关方

输出检查清单

  • 已定义迁移阶段(5-7 个阶段)
  • 双写实现
  • 回填脚本已就绪
  • 验证策略
  • 已配置功能标记
  • 各阶段的回滚计划
  • 风险缓解策略
  • 沟通计划
  • 监控仪表板
  • 测试检查清单

评论

支持 Markdown