Browse Source

docs(task4): harden rollback runbook for sqlite migration

Refine the Task4 rollback plan with executable SQL, explicit schema restoration targets, and post-rollback validation checks so rollback readiness is auditable before Task5.

Made-with: Cursor
main
npmrun 3 weeks ago
parent
commit
4ff41c1ce6
  1. 61
      docs/superpowers/specs/2026-04-20-comment-email-config-design.md

61
docs/superpowers/specs/2026-04-20-comment-email-config-design.md

@ -237,14 +237,59 @@
- 仅在维护窗口执行,暂停写入评论相关流量,避免迁移过程中出现并发写导致数据不一致。
- 执行前完成数据库备份(至少一份可恢复快照),并验证备份可用性后再开始回滚。
### 10.3 回滚步骤(可执行)
1. 创建临时表(例如 `post_comments_rollback`),字段集合与回滚前结构一致,**不包含** `guest_email`、`guest_is_anonymous`。
2. 将原 `post_comments` 的保留字段按列名显式写入临时表(禁止 `SELECT *`,避免列位错配)。
3. 删除或重命名原 `post_comments` 表。
4. 将临时表重命名为 `post_comments`,完成结构替换。
5. 按回滚前定义重建 `post_comments` 相关索引、唯一约束与外键约束(如有)。
6. 执行完整性校验(记录条数、关键查询、外键检查)并恢复流量。
### 10.3 回滚步骤(可执行,针对 migration `0009_curly_jack_murdock.sql`
> 说明:以下步骤用于撤销 Task4 新增列 `guest_email`、`guest_is_anonymous`,并恢复到 `0002_post-comments.sql` 对应的 `post_comments` 结构。
```sql
PRAGMA foreign_keys = OFF;
BEGIN TRANSACTION;
CREATE TABLE `post_comments_rollback` (
`id` integer PRIMARY KEY NOT NULL,
`post_id` integer NOT NULL,
`parent_id` integer,
`author_user_id` integer,
`guest_display_name` text,
`body` text NOT NULL,
`kind` text NOT NULL,
`deleted_at` integer,
`deleted_by_user_id` integer,
`created_at` integer DEFAULT (cast((julianday('now') - 2440587.5) * 86400000 as integer)) NOT NULL,
`updated_at` integer DEFAULT (cast((julianday('now') - 2440587.5) * 86400000 as integer)) NOT NULL,
FOREIGN KEY (`post_id`) REFERENCES `posts` (`id`) ON UPDATE no action ON DELETE cascade,
FOREIGN KEY (`parent_id`) REFERENCES `post_comments_rollback` (`id`) ON UPDATE no action ON DELETE no action,
FOREIGN KEY (`author_user_id`) REFERENCES `users` (`id`) ON UPDATE no action ON DELETE set null,
FOREIGN KEY (`deleted_by_user_id`) REFERENCES `users` (`id`) ON UPDATE no action ON DELETE set null
);
INSERT INTO `post_comments_rollback` (
`id`, `post_id`, `parent_id`, `author_user_id`, `guest_display_name`,
`body`, `kind`, `deleted_at`, `deleted_by_user_id`, `created_at`, `updated_at`
)
SELECT
`id`, `post_id`, `parent_id`, `author_user_id`, `guest_display_name`,
`body`, `kind`, `deleted_at`, `deleted_by_user_id`, `created_at`, `updated_at`
FROM `post_comments`;
DROP TABLE `post_comments`;
ALTER TABLE `post_comments_rollback` RENAME TO `post_comments`;
CREATE INDEX `post_comments_post_id_idx` ON `post_comments` (`post_id`);
CREATE INDEX `post_comments_parent_id_idx` ON `post_comments` (`parent_id`);
COMMIT;
PRAGMA foreign_keys = ON;
```
执行后校验(至少包含以下检查):
1. 行数一致:`SELECT COUNT(*) FROM post_comments;` 与回滚前快照对比。
2. 结构一致:`PRAGMA table_info('post_comments');` 中不应包含 `guest_email`、`guest_is_anonymous`。
3. 外键一致:`PRAGMA foreign_key_check;` 返回空集。
4. 关键查询回归:按 `post_id`、`parent_id` 的评论查询可正常命中索引并返回结果。
若任一步骤失败,停止后续操作并使用回滚前备份恢复,不做“半回滚”上线。
### 10.4 风险与注意事项

Loading…
Cancel
Save