SQLite / 博客文章

Lobste.rs 现已运行在 SQLite 上

约 2 小时前发布

原文链接:https://lobste.rs/s/ko1ji1/lobste_rs_is_now_running_on_sqlite

核心结论

上周六(7 月 11 日),作者与 @pushcx 将 SQLite 迁移 PR 部署到生产环境,并特意等到周一流量高峰验证后才发文。结果非常顺利:CPU 占用下降、内存占用下降、网站响应更快,下线 MariaDB 服务器后 VPS 成本减半,周一高峰"风平浪静"。拖延多年的 #539"迁移到 SQLite" issue 正式关闭。

背景与过程

  • 起因:2019 年就有人讨论迁出 MariaDB,当时倾向于 PostgreSQL;2025 年 K1 收购 MariaDB 后重燃讨论,随后有人提出"Lobsters 能不能跑在 SQLite 上?",作者(有大型数据库迁移经验)于 2025 年 6 月正式接手。
  • 第一次部署(2 月 21 日)失败:上线后仅只读流量就把 CPU 打满 100%,只能回滚。原因是无法接触生产数据,性能问题难以提前发现。
  • 第二次部署(7 月 11 日)成功:期间作者写了批量造数脚本(花一周在本地生成相当于 lobsters 一半数据量的测试数据),修复了三个性能问题——两个查询在最大表上触发全表扫描,第三个是 N+1 查询;并加了慢查询日志以防万一。上线后监控到的小问题也迅速修复。

SQLite 踩坑经验

  1. SQLite gem 支持用户自定义函数(UDF),用它补齐了 regexpifstddev 等 MariaDB 有而 SQLite 没有的函数,减少 SQL 改写量。
  2. SQLite 不支持无符号 bigint,原库中的 unsigned bigint id 需改为普通 bigint。
  3. SQLite 的排序规则(collation)较弱:从 utf8mb4_general_ci 换成 NOCASE,但后者只支持 ASCII 大小写折叠,不支持完整 UTF。
  4. 全文搜索表应使用 Contentless-Delete Tables(非默认选项)。作者感慨"SQLite 的默认选项总让我意外"。

Rails 与代码库经验

  • Rails 默认的 PRAGMA 配置对 lobsters 够用。
  • 数据库 migration 是数据库相关的——旧 migration 需移到单独目录,db:migrate 才能正常工作。
  • lobsters 的测试套件是迁移成功的关键保障,省去了大量手工测试。

总体感悟

  1. 良好沟通是项目成功的关键
  2. 在拿不到生产数据库的情况下做底层数据库迁移非常难——教训是:今后迁移前一定要准备与生产规模相当的数据集。
  3. 两个愿望:① 测试能做到"遇到全表扫描就失败"(本可提前发现首部署的性能问题);② 构造生产级测试数据不该这么费劲(手写脚本 + 等一周)。

加入开源交流群

请加站长微信,免费进入交流群,和开源爱好者一起讨论。

站长微信二维码