数据库迁移实战复盘:独立产品演进中的「零停机」策略 数据库迁移实战复盘独立产品演进中的「零停机」策略一、当 SQLite 开始「不够用」独立产品的数据库选型大多从 SQLite 开始。SQLite 的零运维、单文件备份、和足够的性能让它成为产品验证期的最佳选择。但在产品增长到一定阶段后你可能会遇到 SQLite 的瓶颈写入并发量超过 SQLite 的处理能力通常在几百 QPS 级别或者需要跨区域的低延迟读取SQLite 是单机文件无法做跨区域复制。这时数据库迁移就成为必须面对的工程挑战。这个挑战不只是「把数据从 SQLite 迁到 PostgreSQL」而是「在迁移过程中产品继续服务用户且用户感知不到迁移在发生」。这篇文章将复盘过去一年独立产品在数据库迁移中的实战经验给出「零停机迁移」的可操作策略。二、零停机迁移的四个阶段数据库迁移不是「某天深夜停服 2 小时迁完再开服」。这种「停服迁移」在小规模阶段可能可行但随着用户规模增长停服的成本用户流失、品牌信任下降会越来越高。更可行的策略是「零停机迁移」——把迁移过程拆成多个阶段每个阶段都可以独立验证和回滚且整个过程中产品持续可用。阶段一双写准备期在正式迁移前先让产品支持「双写」——即新数据同时写入 SQLite 和 PostgreSQL或你选择的目标数据库。这个阶段读取操作仍然从 SQLite 读取因为它是当前的主数据库数据是完整的。写入操作同时写两个数据库但 PostgreSQL 的数据暂时只作为「备份」不参与读取。双写准备期的时长取决于你的产品数据量。如果产品有 10 万条核心数据记录用脚本把历史数据从 SQLite 迁移到 PostgreSQL可能只需要几十分钟到几小时。如果数据量是百万级可能需要分段迁移并在迁移过程中做数据校验。阶段二数据校验与补偿在双写准备期完成后你需要验证「PostgreSQL 中的数据是否和 SQLite 完整一致」。校验策略通常是写一个简单的校验脚本逐表对比 SQLite 和 PostgreSQL 中的数据记录。如果发现不一致可能来自双写期间的写入失败需要写「补偿脚本」来修复。这个阶段是最耗时、也最容易出问题的。一个典型的踩坑是SQLite 和 PostgreSQL 的数据类型处理方式不同如 SQLite 的TEXT字段可以存任意长度字符串而 PostgreSQL 的VARCHAR(n)有长度限制。如果在双写时没有处理好这些差异校验阶段会发现大量不一致。阶段三切换读取当数据校验通过后可以开始「切换读取」——把产品的读取操作从 SQLite 逐渐切换到 PostgreSQL。切换策略建议是「灰度切换」先切换 5% 的读取流量到 PostgreSQL观察是否有性能问题或数据不一致如果没问题再切换到 20%、50%、最后 100%。灰度切换的价值是如果 PostgreSQL 在某个查询模式上性能不如预期你可以快速回滚到 SQLite而不影响所有用户。这个回滚机制需要在切换前就写好——在产品配置中加一个「读取数据源」的开关可以在运行时动态调整。阶段四下线 SQLite当读取和写入都已经在用 PostgreSQL且运行稳定通常观察 1-2 周可以下线 SQLite。下线步骤包括关闭双写只写 PostgreSQL、备份 SQLite 文件作为最后的安全网、和从部署配置中移除 SQLite 相关配置。三、迁移中的三个常见陷阱数据库迁移在工程上已经被讨论了很多年但独立开发者在实际执行时仍然容易掉入几个典型陷阱。陷阱一「一次迁移太多表」。有些团队在做迁移时试图「一次性迁移所有表」。这种策略的问题是如果迁移过程中某张表出了问题回滚和调试的成本很高。更可行的策略是「按表分批迁移」——先迁移「数据量小、且读写模式简单」的表如配置表、枚举表验证没问题后再迁移核心业务表。陷阱二「忽略索引和约束的迁移」。SQLite 和 PostgreSQL 在索引和约束的定义语法上有差异。如果迁移脚本只迁了表结构和数据但忽略了索引和约束那么切换读取后你可能会发现「某个查询突然变慢了」因为索引没迁过来或者「某个数据一致性检查突然不生效了」因为约束没迁过来。陷阱三「没有做回滚计划」。很多迁移方案只设计了「正向迁移」的步骤但没有设计「如果出问题怎么快速回滚」。在零停机迁移的四个阶段中每个阶段都应该有明确的回滚触发条件和回滚步骤。比如在阶段三切换读取中如果 PostgreSQL 的响应时间突然大幅上升应该能「在 5 分钟内把所有读取流量切回 SQLite」。四、独立开发者的迁移决策框架对于独立开发者决定是否做数据库迁移、以及什么时候做可以用一个简单的框架来判断。判断维度一SQLite 是否真的成为瓶颈在决定迁移前先用监控数据确认「SQLite 的性能瓶颈是可复现的」而不是「某次慢查询是因为索引没加对」。一个典型的误判是产品偶尔出现慢查询开发者以为是「SQLite 不够用了」但实际上只是某条 SQL 没加索引。在这种场景下「加索引」或「优化 SQL」就能解决问题不需要迁移数据库。判断维度二迁移的收益是否大于成本数据库迁移的工程成本不低通常需要 1-2 周的开发 测试 观察。如果迁移后的收益只是「为未来可能的规模做准备」而这个「可能的规模」在接下来 6 个月内都不会到来那么迁移的优先级可能不高。更务实的策略是「等规模真正到来时再迁移」而不是「提前迁移以应对未来」。判断维度三团队是否有迁移所需的工程能力数据库迁移需要理解「数据一致性」、「灰度切换」、和「回滚机制」这些工程概念。如果团队或独立开发者没有相关经验迁移的风险会比较高。这种场景下更可行的策略可能是「先用管理式数据库服务如 Supabase、Neon」而不是「自己管理 PostgreSQL 实例 做迁移」。管理式服务通常提供「一键迁移」或「逻辑复制」功能能降低迁移的复杂度。五、总结数据库迁移是独立产品演进中的「高价值、高风险」工程任务。零停机迁移的核心策略是「分阶段、可灰度、可回滚」——把迁移拆成双写准备、数据校验、切换读取、和下线旧数据库四个阶段每个阶段都可以独立验证和回滚。迁移中的三个常见陷阱包括一次迁移太多表应该按表分批、忽略索引和约束的迁移导致切换后性能问题、以及没有做回滚计划出问题时无法快速恢复。对于独立开发者迁移决策应该用三个维度来判断SQLite 是否真的成为瓶颈先用监控数据确认而不是凭感觉、迁移的收益是否大于成本避免为「未来可能的规模」提前做复杂工程、以及团队是否有迁移所需的工程能力如果没有优先考虑管理式数据库服务的迁移工具。好的数据库迁移是「让用户感知不到迁移在发生」——产品持续可用且迁移完成后用户获得的是「更稳定的性能」而不是「新的使用摩擦」。资料说明本文中的协议、版本、性能、成本和行业趋势应以可核验的一手资料为准。未标注统计口径的比例、时间表和预测仅作工程讨论不应视为行业事实。可参考 0730 资料来源索引并在发布前将具体来源贴到对应断言之后。