mcpField
D
database-migration

database-migration

github.com/seb1n数据与数据库236129 次安装12 周前更新
代码仓库

关于 database-migration

database-migration 是帮助 AI Agent 规划和编写版本化数据库结构变更的技能,适用于负责数据库演进的开发团队。它涵盖回滚、数据回填和零停机部署策略,并支持多种迁移框架。

主要功能

  1. 01评估结构变更风险
  2. 02生成升级与回滚脚本
  3. 03处理数据回填
  4. 04规划扩展与收缩迁移
  5. 05在暂存环境验证迁移
  6. 06监控部署后的状态

适用场景

  1. 01为新增字段生成迁移脚本
  2. 02安全重命名数据库列
  3. 03规划分阶段生产环境部署
  4. 04在 CI 中测试升级和回滚

安装

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

$npx skills add https://github.com/seb1n/awesome-ai-agent-skills --skill database-migration

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

详细介绍

数据库迁移

此技能可让 AI Agent 通过迁移框架管理带版本控制的数据库架构变更。Agent 会创建正向和回滚迁移脚本,在架构变更期间处理数据回填,采用安全的迁移模式确保部署零停机,并将迁移工作流集成到 CI/CD 流水线中。支持的主要工具包括 Alembic(Python/SQLAlchemy)、Prisma Migrate(TypeScript/Node)、Flyway(Java/SQL)和 Knex(JavaScript)。

工作流

  1. 评估架构变更: 分析所请求的变更——添加列、创建表、修改约束、重命名字段或转换数据。将变更归类为向后兼容(增量式)或有破坏性(破坏式),以确定部署策略。有破坏性的变更需要采用多阶段迁移方案。

  2. 选择迁移工具: 根据项目的技术栈选择合适的迁移框架。Python/SQLAlchemy 项目使用 Alembic,TypeScript/Prisma 项目使用 Prisma Migrate,Java 或 SQL 优先的工作流使用 Flyway,Node.js/Express 项目使用 Knex。确保该工具已初始化并连接到目标数据库。

  3. 生成迁移脚本: 在支持的情况下,根据架构差异自动生成迁移(Alembic autogenerate、Prisma migrate dev),然后检查并编辑生成的脚本。添加明确的回滚(降级)逻辑。对于数据回填,在迁移中加入数据转换,以确保架构和数据变更是原子的。

  4. 在预发布环境中测试: 对与生产环境相匹配的预发布数据库应用迁移。验证迁移能否顺利应用、现有查询是否仍能正常运行,以及回滚是否能恢复到先前状态。针对迁移后的架构运行应用程序测试套件。

  5. 采用零停机策略部署: 生产环境使用扩展和收缩式迁移。阶段 1:添加新列/新表(扩展),不移除旧结构。阶段 2:部署同时向新旧结构写入数据的应用程序代码。阶段 3:回填数据。阶段 4:部署仅使用新结构的代码。阶段 5:移除旧列/旧表(收缩)。这样可确保零停机,并在每个阶段都能安全回滚。

  6. 验证并监控: 部署后,使用框架的状态命令验证迁移状态。监控应用程序日志和数据库性能,检查是否出现回归。确认所有迁移元数据都已记录在框架的版本表中。

支持的技术

  • Alembic: Python、SQLAlchemy、PostgreSQL/MySQL/SQLite
  • Prisma Migrate: TypeScript/JavaScript、Prisma ORM、PostgreSQL/MySQL/SQLite/SQL Server
  • Flyway: Java、基于 SQL 的迁移、所有主流 RDBMS
  • Knex: JavaScript/TypeScript、Node.js、PostgreSQL/MySQL/SQLite
  • Django Migrations: Python、Django ORM
  • Sequelize: JavaScript、Node.js ORM

用法

描述所需的架构变更(例如,“向 users 表添加一个 phone_number 列”),并说明项目使用的迁移框架。Agent 将生成包含升级和降级逻辑的迁移文件,提供应用迁移的说明,并为生产环境提供安全部署策略建议。

示例

示例 1:Alembic 迁移 — 添加列并回填数据

请求: 向 users 表添加一个 display_name 列,并通过拼接 first_name 和 last_name 为其回填数据。

生成迁移:

alembic revision --autogenerate -m "add_display_name_to_users"

迁移文件(versions/20250115_add_display_name_to_users.py):

"""add display_name to users

Revision ID: a1b2c3d4e5f6
Revises: 9z8y7x6w5v4u
Create Date: 2025-01-15 10:30:00.000000
"""
from alembic import op
import sqlalchemy as sa

revision = "a1b2c3d4e5f6"
down_revision = "9z8y7x6w5v4u"
branch_labels = None
depends_on = None


def upgrade():
    # Phase 1: Add the column as nullable (safe, no locks on reads)
    op.add_column("users", sa.Column("display_name", sa.String(300), nullable=True))

    # Phase 2: Backfill existing rows
    users = sa.table(
        "users",
        sa.column("id", sa.Integer),
        sa.column("first_name", sa.String),
        sa.column("last_name", sa.String),
        sa.column("display_name", sa.String),
    )
    op.execute(
        users.update().values(
            display_name=sa.func.concat(
                users.c.first_name, " ", users.c.last_name
            )
        )
    )

    # Phase 3: Set NOT NULL after backfill is complete
    op.alter_column("users", "display_name", nullable=False)


def downgrade():
    op.drop_column("users", "display_name")

应用并验证:

alembic upgrade head
alembic current   # Confirms: a1b2c3d4e5f6 (head)
示例 2:Prisma Migrate — 添加 Reviews 模型

请求: 在 Prisma 项目中添加一个关联到 User 和 Product 的 Review 模型。

更新 prisma/schema.prisma:

model Review {
  id        Int      @id @default(autoincrement())
  rating    Int      @db.SmallInt
  comment   String?  @db.Text
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
  userId    Int
  productId Int
  user      User     @relation(fields: [userId], references: [id], onDelete: Cascade)
  product   Product  @relation(fields: [productId], references: [id], onDelete: Cascade)

  @@unique([userId, productId])
  @@index([productId])
  @@index([rating])
}

生成并应用迁移:

npx prisma migrate dev --name add_reviews_table

生成的 SQL(prisma/migrations/20250115_add_reviews_table/migration.sql):

CREATE TABLE "Review" (
    "id" SERIAL NOT NULL,
    "rating" SMALLINT NOT NULL,
    "comment" TEXT,
    "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "updatedAt" TIMESTAMP(3) NOT NULL,
    "userId" INTEGER NOT NULL,
    "productId" INTEGER NOT NULL,
    CONSTRAINT "Review_pkey" PRIMARY KEY ("id")
);

CREATE INDEX "Review_productId_idx" ON "Review"("productId");
CREATE INDEX "Review_rating_idx" ON "Review"("rating");
CREATE UNIQUE INDEX "Review_userId_productId_key" ON "Review"("userId", "productId");
ALTER TABLE "Review" ADD CONSTRAINT "Review_userId_fkey"
    FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE;
ALTER TABLE "Review" ADD CONSTRAINT "Review_productId_fkey"
    FOREIGN KEY ("productId") REFERENCES "Product"("id") ON DELETE CASCADE;

最佳实践

  • 始终为每次迁移编写明确的降级/回滚逻辑,以便在部署引发问题时安全地恢复。切勿假设在时间紧迫时可以手动撤销迁移。
  • 通过扩展再收缩的方式确保迁移向后兼容:先添加新结构,再迁移数据,最后在新代码完全部署后,通过单独的迁移移除旧结构。
  • 切勿未经审核就运行自动生成的迁移——自动检测工具遇到重命名字段时,可能会生成破坏性操作(删除列)。务必检查生成的 SQL。
  • 在支持的情况下对 DDL 使用事务(PostgreSQL 会将 DDL 包装在事务中;MySQL 不会)。对于不支持事务的 DDL 数据库,要规划好部分失败后的恢复方案。
  • 让迁移保持小而专一——每个迁移文件只包含一项逻辑变更。这样可以细化回滚粒度,也更容易找出导致问题的迁移。
  • 在 CI 中针对临时数据库运行迁移,以便在错误进入生产环境前将其发现。测试中应同时包含升级和降级路径。

边缘情况

  • 大型表迁移: 在旧版 PostgreSQL 中,为包含数百万行的表添加带默认值的 NOT NULL 列可能会锁定表数分钟。可使用 ADD COLUMN ... DEFAULT ... NOT NULL(在 PostgreSQL 11+ 中不会锁表),或者先添加为可空列,分批回填,再设置为 NOT NULL。
  • 重命名列: 大多数迁移工具会将重命名视为删除后再添加,从而导致数据丢失。使用 Alembic 中的 op.alter_column() 或原始 ALTER TABLE ... RENAME COLUMN 来执行真正的重命名。应用前请核验生成的迁移。
  • 并发迁移: 在多实例部署中,确保只有一个实例运行迁移。使用 advisory 锁(Flyway 和 Alembic 支持此功能),或通过部署流水线在滚动发布应用实例前将迁移作为专门步骤运行。
  • 枚举类型变更: 向 PostgreSQL 枚举中添加值不能在事务中执行。创建新的枚举类型,迁移列,然后删除旧类型。也可以改用带 CHECK 约束的 VARCHAR,以便更轻松地修改。
  • 仅数据迁移: 当需要在不更改架构的情况下转换数据(例如加密列中的值)时,仍应使用迁移文件,以便对其进行版本管理,并确保在不同环境中可重复执行。

评论

支持 Markdown