laoyang
9f41e1622e
v45-① 同步基础字段:53 张业务表补 updated_at + deleted_at(结构 v33)
用户 2026-10-12 定「本地优先(local-first)」架构,客户端要落盘 + 增量同步。
本批只做**服务端地基**(不含客户端代码)。
## 为什么必须补这两个字段
增量同步要先能回答两个问题,而实测现状两个都答不了:
· **哪些行变了?** —— 50 张表里只有 21 张有 `updated_at`
(`anniversaries` / `ledger_entries` / `task_boards` 等都没有);
· **哪些行被删了?** —— **一张有 `deleted_at` 的都没有**。
硬删除在客户端**永远不可见**(没有墓碑,无法区分"服务端删了"与"本地没拉到")
⇒ 会一直显示幽灵数据。
## 做法
· 53 张业务表补 `updated_at`:
`DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP`
—— **由 MySQL 自己维护**,任何真实 UPDATE 都自动刷新。
⇒ **业务代码一行都不用改**,也就不存在"某处忘了更新 updated_at"的漏网之鱼
(手工 `SET updated_at = NOW()` 那种做法迟早会漏)。
· 53 张业务表补 `deleted_at`(软删除墓碑,NULL = 未删)。
⚠️ 本批**只加列、不改删除逻辑** —— 改成软删除是后续独立一步,
先加列的好处是那步开始时不必再动表结构。
· 按有无 `family_id` 加 `idx_<表>_sync` 索引,供 `WHERE family_id=? AND updated_at>?` 用。
· ⛔ 8 张**故意不加**(凭据/字典/本地偏好):`api_tokens` `dav_credentials`
`settings` `user_settings` `regions` `nav_engines` `nav_settings` `weread_snapshots`
—— 同步白名单应当显式而简短。
## 过程中发现并修正的一个清单缺陷(重要)
第一版清单**只扫了 `statements()`**,漏掉 11 张"建在 `ensure()` 迁移段里"的表
(`anniversaries` / `ledgers` / `ledger_entries` / `ledger_shares` /
`ledger_entry_snapshots` / `task_boards` / `task_categories` /
`calendar_event_skips` / `anniversary_people` / `person_jobs` / `person_notes`)。
**线上实测才发现 `anniversaries` 没有 updated_at。**
⇒ 教训:找"全部表"必须扫**整个文件**(本文件建表语句分散在两个函数里),
只扫建表函数必然漏。
## 验证(线上实测)
· `deleted_at` 53 列 / `idx_*_sync` 53 张 —— 与清单精确一致 ✓
· **`ON UPDATE` 真的生效**:改 `cinemas.name` 后
`updated_at` 16:19:19 → 16:27:28 自动刷新 ✓(业务代码未插手)
⚠️ 首次测试误报"没生效":当时用 `SET name = name`(**值没变**),
MySQL 本来就不触发 ON UPDATE —— 是测试方法错,不是缺陷。
· 回归:首页/people/calendar/api 均 302/401(未登录的正常响应),无 500 ✓
· 诊断页用完即删、404 复验通过 ✓
2026-10-12 16:28:29 +08:00
..
2026-09-30 20:22:46 +08:00
2026-09-30 00:49:53 +08:00
2026-09-30 13:24:26 +08:00
2026-10-07 11:35:31 +08:00
2026-10-12 15:31:03 +08:00
2026-10-12 15:31:03 +08:00
2026-10-12 15:31:03 +08:00
2026-10-03 08:18:05 +08:00
2026-10-06 17:33:48 +08:00
2026-10-02 09:28:07 +08:00
2026-10-03 08:18:05 +08:00
2026-10-05 10:58:17 +08:00
2026-10-05 10:58:17 +08:00
2026-10-05 10:58:17 +08:00
2026-10-03 15:01:38 +08:00
2026-10-11 10:12:11 +08:00
2026-10-12 00:24:20 +08:00
2026-10-11 10:12:11 +08:00
2026-10-06 20:41:04 +08:00
2026-10-01 00:12:04 +08:00
2026-10-06 17:33:48 +08:00
2026-10-04 08:56:40 +08:00
2026-09-30 00:49:53 +08:00
2026-09-30 00:49:53 +08:00
2026-10-03 20:23:22 +08:00
2026-10-05 13:26:49 +08:00
2026-09-30 00:49:53 +08:00
2026-10-05 16:45:10 +08:00
2026-10-12 15:31:03 +08:00
2026-10-04 19:43:00 +08:00
2026-10-07 05:52:40 +08:00
2026-10-05 10:58:17 +08:00
2026-10-08 20:05:01 +08:00
2026-10-05 10:58:17 +08:00
2026-10-03 08:18:05 +08:00
2026-10-07 15:31:26 +08:00
2026-09-30 09:44:55 +08:00
2026-10-08 02:20:19 +08:00
2026-10-07 18:22:55 +08:00
2026-10-09 20:23:09 +08:00
2026-10-01 00:12:04 +08:00
2026-10-11 10:12:11 +08:00
2026-10-08 02:20:19 +08:00
2026-10-07 05:52:40 +08:00
2026-09-30 13:24:26 +08:00
2026-10-05 16:45:10 +08:00
2026-10-08 10:54:43 +08:00
2026-10-09 07:25:08 +08:00
2026-10-04 08:56:40 +08:00
2026-09-30 13:24:26 +08:00
2026-10-03 19:27:14 +08:00
2026-10-03 19:27:14 +08:00
2026-10-04 08:56:40 +08:00
2026-10-08 02:20:19 +08:00
2026-10-08 02:20:19 +08:00
2026-10-03 11:30:48 +08:00
2026-10-07 11:35:31 +08:00
2026-10-02 22:08:13 +08:00
2026-10-03 11:30:48 +08:00
2026-10-03 15:01:38 +08:00
2026-10-12 16:28:29 +08:00
2026-09-30 00:49:53 +08:00
2026-10-06 03:14:18 +08:00
2026-10-12 15:31:03 +08:00
2026-10-11 10:12:11 +08:00
2026-10-02 09:28:07 +08:00
2026-09-30 11:06:22 +08:00
2026-10-06 17:33:48 +08:00
2026-10-05 16:45:10 +08:00
2026-10-10 22:13:20 +08:00
2026-10-08 10:54:43 +08:00
2026-10-08 10:54:43 +08:00