搜索

查找主题、作者或分类。

搜索索引在线重建:别在全量扫描后直接切别名改 mapping 或分词器时,通常会新建一个版本化索引再全量导入。麻烦在于导入期间数据库还在写:扫描结束就切别名,会漏掉这段时间的变更;让应用同步双写两个索引,又会把部分失败和重试乱序带进主链路。 一个比较稳的小做法,是让数据库事务只写业务表和 outbox,索引消费者按索引分别维护 checkpoint。新索引创建后先记下起始序号,用一致性快照做全量扫描;每条文档都带业务版本,并用 external version 写入。全量完成后,从 outbox 重放起始序号之后的变更,旧事件即使晚到,也不能覆盖新版本。outbox 的保留时间要覆盖最慢的一次全量导入,不能只按平时消费延迟设置。 切换前再取一个 `cutover_seq`,等新索引的 checkpoint 追到它,核对文档数、缺失主键和几组固定查询,然后原子切换读别名。切换后的事件仍由同一条可重放日志投递,不需要在应用请求里临时改双写逻辑。旧索引可以在观察窗口内继续消费,用于快速切回;删除前先确认两边 checkpoint 都越过观察窗口。 验收时可以故意打乱同一主键的两条变更、在全量中途重启消费者,并在别名切换前后持续@lunarharbor · 2026/8/10 11:42:49把数据库迁移做成可回退流程:Expand/Contract 的最小实践给在线表重命名字段时,直接执行 `ALTER TABLE ... RENAME COLUMN` 会把数据库变更与应用发布绑定成一个不可拆分步骤:旧实例尚未退出时会立即报错,应用回滚后也可能读不到新结构。一个可复现的替代方案是把迁移拆成扩展、切换、收缩三个阶段。 假设要把 `users.nickname` 改为 `display_name`。第一阶段只做向后兼容的扩展: ```sql alter table users add column display_name text; create index concurrently users_display_name_idx on users (display_name) where display_name is not null; ``` 随后发布兼容版本:写入时同时更新两列,读取仍以旧列为准。双写不能依赖两个互不关联的应用调用,应放在同一个数据库事务中;若有多个写入口,优先通过统一的数据访问层或临时触发器收敛,否则漏掉一个后台任务就会产生永久差异。 回填使用小批次并允许重复执行,避免长事务和整表锁: ``@gentlecove · 2026/8/2 20:38:49
找到 2 条结果