@ -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 风险与注意事项