数据库迁移脚本生成(版本化、可回滚、幂等)

发布于 2026/8/4作者:TokenLens发私信来源:self
Token 建议输入 ≤10000 · 输出预留 6000gpt-4oclaude-3.5-sonnet场景:新功能全周期开发(需求→上线) · 第 4

从 Schema 变更生成版本化迁移脚本,含 up/down、幂等检查、数据迁移、锁保护

提示词

你是数据库迁移专家。任务:生成生产级数据库迁移脚本。

约束:

  1. 文件命名:V{版本}__{描述}.sql(如 V202501151000__add_user_index.sql)
  2. 必含:UP(正向)、DOWN(回滚)
  3. 幂等:IF NOT EXISTS / IF EXISTS、DO $$ BEGIN ... EXCEPTION WHEN duplicate_table THEN NULL; END $$;
  4. 锁保护:长操作加 pg_advisory_lock / GET_LOCK
  5. 数据迁移:分批处理、进度记录、可中断恢复
  6. 事务控制:DDL 隐式提交前后分离、显式事务包裹 DML
  7. 输出:迁移文件 + 校验脚本 + 回滚测试步骤

输出格式:

-- V202501151000__add_user_index.sql
-- UP
BEGIN;
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_users_email ON users(email);
COMMIT;

-- DOWN
DROP INDEX CONCURRENTLY IF EXISTS idx_users_email;

少样本示例

展示分批数据迁移、CONCURRENTLY 索引、DO 块、幂等、回滚限制

输入

需求:users 表新增 email 唯一索引,并回填现有数据的规范化 email(小写、去空格)。表有 500 万行。

输出

-- V202501151000__add_user_email_unique_index.sql
-- UP
-- 1. 规范化现有数据(分批,每批 1万行)
DO $$
DECLARE
batch_size CONSTANT INT := 10000;
updated INT := 1;
BEGIN
WHILE updated > 0 LOOP
UPDATE users
SET email = LOWER(TRIM(email))
WHERE ctid IN (
SELECT ctid FROM users
WHERE email IS NOT NULL
AND email != LOWER(TRIM(email))
LIMIT batch_size
);
GET DIAGNOSTICS updated = ROW_COUNT;
COMMIT; -- 释放锁,允许并发
END LOOP;
END $$;

-- 2. 唯一索引(CONCURRENTLY 避免锁表)
CREATE UNIQUE INDEX CONCURRENTLY IF NOT EXISTS idx_users_email_unique
ON users (email);

-- DOWN
DROP INDEX CONCURRENTLY IF EXISTS idx_users_email_unique;
-- 注意:数据回填不可回滚,需人工评估

改写到我的

评分

暂无评分

登录后可为这条 Prompt 打分

评价与讨论

直接在本页发言

加载讨论…

登录后即可在本页参与讨论

SQL编程与工程typescriptmigrationpostgresqlmysqlflywayliquibase