Files
backend_v2/db/migrations/README.md
toom1996 f04b5707cb fix(publish): 最终审查补修(编辑页删图重算计数、迁移编号后置、图片 id 稳定断言)
D1 编辑页删图:DeleteRunwayImage/DeleteSnapImage 在单事务内取父 id→软删→按存活行重算 image_count,口径与审核侧 SoftDelete*Image 完全一致(走秀只计主图、街拍计全部),并补集成测试(含重复删同一张)

D2 不可逆删表迁移 02→05(git mv),使文件名顺序 01→01b→03→04→05 与必需执行顺序一致;同步 README/文件头/规格/计划全部引用

D3 新增「通过审核后图片行 id 集合完全一致」的集成断言,锁住单表发布头号收益

D4 修正 01 迁移文件头「只做三件事」自相矛盾表述;D5 删除受版本控制的陈旧产物 cmd/dbtool/db_dump.json 并加 gitignore 规则;D6 清理遗留空目录 scripts/tmp_verify/
2026-09-23 16:27:14 +08:00

56 lines
4.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 数据库迁移
本目录的 `.sql` 是**手工一次性迁移**(服务启动不做 DDL,结构由 `dbtool` 导出的 `db_dump.sql` 维护)。
命名规则 `日期-序号-主题.sql`,**按文件名顺序执行**。
- 全新库:直接用 `db_dump.sql` 建库(见根目录 `README.md`「数据库」一节),**不需要**跑这些迁移。
- 存量库升级:按下文顺序执行;大多语句幂等,但**数据变更类不可重放**(见各步说明)。
---
## 一、2026-09-21 系列(街拍主副图 / 重复检测 / 来源幂等)
| 顺序 | 文件 | 说明 |
| --- | --- | --- |
| 1 | `2026-09-21-01-street-main-detail.sql` | 草稿表与正式图片表加 `is_detail` / `parent_image_id`。全 `IF NOT EXISTS`,幂等。 |
| 2 | `2026-09-21-02-duplicate-review.sql` | 新建 `image_duplicates`,街拍正式表加 `source` / `source_url` 及部分唯一索引 `uq_ss_source`。幂等。 |
| 3 | `2026-09-21-03-ingest-source-idempotency.sql` | 两张**草稿表**加 `source` / `source_url` 及部分唯一索引。幂等。这些列会随 2026-09-22-05 删草稿表一并消失。 |
这三步属于更早的改造;对已经过它们的库重放无害。
---
## 二、2026-09-22 单表发布(草稿表 → 单表 + `status` + 公开只读视图)
**执行顺序:`01 → 01b → 03 → 04 → 搬迁脚本 → 05`**(与文件名排序一致:`01`、`01b`、`03`、`04`、`05`;搬迁脚本是一段独立命令,夹在 `04` 与 `05` 之间执行)
| 顺序 | 对象 | 前提 / 幂等 / 不可逆点 |
| --- | --- | --- |
| 1 | `2026-09-22-01-single-table-publish.sql` | 给 `brand_runways` / `street_snaps` 加 `status` 等列、建状态索引、建 4 个 `public_*` 视图。**幂等**,可重复执行(集成测试每次都会跑它)。 |
| 2 | `2026-09-22-01b-publish-existing-rows.sql` | 把存量正式行置 `published`。**只能执行一次**;且必须在新代码部署**之前**、搬迁脚本**之前**执行。理由:搬迁会把 pending 草稿连同旧 `created_at` 一起搬进来,若这条 UPDATE 可重放,待审内容会被误刷成已发布(本设计要防的就是这个泄漏)。 |
| 3 | `2026-09-22-03-entity-key-unique.sql` | 实体键部分唯一索引 `uq_br_entity` / `uq_ss_entity`(街拍为最终表达式 `(city, year, COALESCE(title,''))`)。**幂等**;建索引前先体检,有重复就报可读错误而非原生 23505。 |
| 4 | `2026-09-22-04-street-entity-key-title.sql` | 街拍索引的**幂等兜底**:`DROP INDEX IF EXISTS uq_ss_entity` 后按最终表达式重建。常态由 03 承载;本文件专治「库里已有同名旧 `(city, year)` 索引、03 因 `IF NOT EXISTS` 静默跳过」的存量库。 |
| 5 | 搬迁脚本 `<见下>` | 把草稿表数据搬进正式表。**一次性**;先 `-dry-run` + 守恒校验,**校验不过绝不进入第 6 步**。 |
| 6 | `2026-09-22-05-drop-draft-tables.sql` | 删除 4 张草稿表。**不可逆**;前提是第 5 步校验通过,且 `db/backups/` 有可用备份。⚠️ 编号排在最后(`05`)是刻意的:按文件名顺序执行的运维者不会在搬迁之前误删草稿表。 |
### 搬迁脚本的取回方式
`scripts/migrate_single_table/main.go` 是一次性工具,已随本次改造从工作树删除(它 `import` 了同批删除的
草稿模型,无法在改造后的代码树上编译)。如需重放,从**它被删除前的最后一个提交**取回:
```bash
# 取回脚本源码(c4bafc5 是删除提交 d68a570 的父提交,即脚本最后一次存在的版本)
git show c4bafc5:scripts/migrate_single_table/main.go
```
注意:脚本依赖草稿模型,必须在该提交(或更早)的代码树上运行,**不能**直接放进当前树。
真正需要重放时,建议 `git worktree add ../old c4bafc5` 切出旧树再跑。
### 索引口径的一个坑
`CREATE UNIQUE INDEX IF NOT EXISTS` 只按**索引名**判断存在性,不比对表达式。因此:
- 若库里已有同名但口径更窄的旧 `uq_ss_entity (city, year)`,03 会静默跳过、留下错误结构;
这时必须跑 04 纠正(04 的 `DROP` 正是为此)。
- 反过来,若只跑 03 而库里已存在正确的同名索引,跳过是无害的。