--- name: db-migration description: 数据库变更方案插件。Migration 脚本生成、数据迁移策略、回滚方案。挂载在 design 阶段,涉及数据库变更时由 req-design 推荐激活。 --- # 数据库变更方案插件 (db-migration) ## 概述 当需求涉及数据库结构变更时使用,确保变更安全、可回滚。 **触发条件**: - 新增/修改/删除表或字段 - 数据迁移(旧数据转换) - 索引优化 ## Migration 规范 ### 文件命名 ``` backend/migrations/YYYYMMDDHHMMSS_description.up.sql # 正向迁移 backend/migrations/YYYYMMDDHHMMSS_description.down.sql # 回滚迁移 ``` ### 安全规则 | 操作 | 风险等级 | 注意事项 | |------|---------|---------| | ADD COLUMN (nullable) | 低 | 安全,无锁表 | | ADD COLUMN (NOT NULL + DEFAULT) | 中 | PG 12+ 不锁表,旧版本锁表 | | DROP COLUMN | 高 | 确认无代码引用,先标记废弃 | | ALTER COLUMN TYPE | 高 | 可能锁表,大表慎用 | | ADD INDEX | 中 | 使用 CONCURRENTLY 避免锁表 | | DROP TABLE | 极高 | 必须确认无依赖 | ### Migration 模板 **新增表**: ```sql -- up.sql CREATE TABLE IF NOT EXISTS xxx ( id BIGSERIAL PRIMARY KEY, tenant_id BIGINT NOT NULL, -- 业务字段 name VARCHAR(255) NOT NULL, status VARCHAR(50) NOT NULL DEFAULT 'active', -- 审计字段 created_by BIGINT, created_at TIMESTAMP NOT NULL DEFAULT NOW(), updated_at TIMESTAMP NOT NULL DEFAULT NOW(), deleted_at TIMESTAMP ); CREATE INDEX idx_xxx_tenant_id ON xxx(tenant_id); CREATE INDEX idx_xxx_deleted_at ON xxx(deleted_at); -- down.sql DROP TABLE IF EXISTS xxx; ``` **新增字段**: ```sql -- up.sql ALTER TABLE xxx ADD COLUMN yyy VARCHAR(255); -- 如果需要索引 CREATE INDEX CONCURRENTLY idx_xxx_yyy ON xxx(yyy); -- down.sql DROP INDEX IF EXISTS idx_xxx_yyy; ALTER TABLE xxx DROP COLUMN IF EXISTS yyy; ``` **数据迁移**: ```sql -- up.sql -- 1. 先添加新字段 ALTER TABLE xxx ADD COLUMN new_field VARCHAR(255); -- 2. 迁移数据 UPDATE xxx SET new_field = old_field WHERE new_field IS NULL; -- 3. 添加约束(数据迁移完成后) ALTER TABLE xxx ALTER COLUMN new_field SET NOT NULL; -- down.sql ALTER TABLE xxx ALTER COLUMN new_field DROP NOT NULL; ALTER TABLE xxx DROP COLUMN IF EXISTS new_field; ``` ## 大表变更策略 当表数据量 > 100 万行时: 1. **添加索引**:必须使用 `CREATE INDEX CONCURRENTLY` 2. **修改字段类型**:分步执行(新增列→迁移数据→切换引用→删除旧列) 3. **添加 NOT NULL**:先添加 DEFAULT,再 SET NOT NULL 4. **数据迁移**:分批处理,每批 1000-10000 行 ## 回滚检查 每个 Migration 必须有可执行的 down.sql: - [ ] down.sql 存在且语法正确 - [ ] down.sql 可以完全撤销 up.sql 的变更 - [ ] down.sql 不会丢失业务数据(除非是 DROP TABLE)