alitrack

自托管DuckDB的三个阶段:MotherDuck写了份避坑指南

昨天,MotherDuck 发了篇长文,标题叫《Self-hosting DuckDB: the road to production》。一家卖 DuckDB 云托管服务的公司,主动教你自托管——这事本身就挺有意思。

文章作者 Mehdi Ouazza 开门见山说了实话:动机是自私的。MotherDuck 见过太多团队自托管 DuckDB 走错了路,撞了墙,然后跑去 Hacker News 上发帖说"DuckDB 不能规模化"——其实问题出在胶水代码上,不是 DuckDB 本身。所以他们决定画一张地图:自托管 DuckDB 要经过哪些阶段,每个阶段要维护哪些组件,什么时候该停下来考虑托管服务。

我把这篇 13 分钟长文的核心内容提炼出来,加上自己的理解,分享给你。

● ● ●

三个阶段,层层加码

MotherDuck 把自托管 DuckDB 的路分成三个阶段。每个阶段,你的系统里都会多一个"要维护的盒子"。到第三阶段,你会发现自己在运营一个完整的数据平台。

阶段一:嵌入式 DuckDB

这是大多数人的起点。一个 Python 脚本,import duckdb,把 CSV 转成 Parquet。跑完就关,零基础设施。

问题出现在你想让第二个应用也访问同一个 DuckDB 文件的时候。

DuckDB 是单进程、单写入者的数据库。两个进程同时打开同一个文件做读写?不行。你会看到这个报错:

Error: unable to open database file "sales.db":
IO Error: Could not set lock on file

这就是阶段一的终点。

解决并发的四个方案,各有利弊:

  • LiteFS:分布式文件系统的 trick。一个 leader 写,followers 复制并服务读取。这不是原生复制,但能用。
  • Quack:DuckDB v1.5 原生的 HTTP 协议,多并发读取开箱即用。但底层还是一个 DuckDB 进程,写入会串行化。
  • 应用层互斥锁:最简单。如果查询够快、并发不高,很多人就这么干的,甚至没意识到自己在做并发控制。
  • 多数据库拆分:按租户、按团队、按场景拆成多个 DuckDB 文件。只要你不做跨库查询,这是最省心的方案。

阶段一的成本:几乎没有。一台机器跑脚本,S3 存数据。如果是每晚跑一次的批处理,你的笔记本就够用。

阶段二:单进程多客户端服务器

你不再只是 import duckdb 了。你需要实时查询、多个应用同时访问。于是你起了一台专用实例,通过 Quack 暴露接口。

从"跑脚本"到"跑服务",这是质变。

跑服务意味着运维:监控、日志、权限、容灾、容量规划。MotherDuck 列了一张你在阶段二要维护的组件清单:

  • 反向代理(Nginx/Envoy/Caddy):路由流量、TLS 终止
  • 负载均衡:多个 Quack 实例分发读请求
  • 指标监控(Prometheus + Grafana):追踪查询性能
  • 健康检查:确保 DuckDB 进程存活
  • 日志聚合:集中收集 DuckDB 的错误输出
  • 自动重启:进程崩溃后恢复
  • 备份流程:文件损坏或误删的保险
  • 密钥管理:S3 凭证、API key
  • 访问控制:DuckDB 本身没有内置认证,你得在代理层做

还有一个容易被忽略的点:物化视图刷新。DuckDB 不会自动刷新物化视图——你得上 cron job 或消息队列。每隔多久刷新一次?每小时?每天?一旦下游形成依赖,改刷新策略就是事故。

阶段二的成本:最大的成本不是基础设施,是人。维护这套系统的人要理解 DuckDB 的锁语义、内存行为、崩溃恢复。没有一个叫"DuckDB 运维工程师"的岗位。只能靠自己。

阶段三:多 DuckDB 进程,统一数据层

你的单机跑不动了。批量作业太久、CPU 打满。你要横向扩展。

这是最折腾的阶段。你的架构变成了标准湖仓一体:

  • 对象存储(S3/GCS/R2/MinIO)作为存储层
  • 开放表格式(DuckLake、Iceberg、Delta Lake)管理数据组织、Schema 演化、时间旅行
  • Catalog(Nessie、Polaris、Unity)管理元数据
  • 多个 DuckDB 进程:ETL、BI、应用各连各的
  • 编排工具(Airflow/Dagster/Temporal)调度流水线
  • 元数据缓存层:减少 Catalog 调用

最棘手的问题是写入者协调。

开放表格式用乐观并发:两个写入者同时写,一个成功,另一个收到冲突错误,得重试。重试逻辑、冲突检测、重新读取最新状态再回放——这些都得你在应用层处理。不是 DuckDB 的 bug,是湖仓架构天然就是这样,现在归你管了。

还有性能陷阱。多进程读同一份数据,瓶颈从计算转移到元数据延迟。DuckCon #7 上 DuckLabs CTO Martin Grund 专门讲了这个问题:从很多 DuckDB 实例同时查 Iceberg 表,需要运行一个元数据复制层才能解决。这就是"冰山"的含义——大部分东西在水面以下。

阶段三的成本:基础设施账单不是瓶颈。真正贵的是团队——你现在需要懂得 Catalog 语义、开放表格式内部机制、元数据缓存、分布式系统故障模式的工程师。你在运营一个小型数据仓库平台。

● ● ●

什么时候该停?

MotherDuck 给出了一个清晰的决策框架:

  • 阶段一:自托管几乎是唯一正确的选择。一个脚本而已,上托管服务是杀鸡用牛刀。
  • 阶段二:要做决定了。如果你的团队有基础设施工程师,愿意自己建监控、备份、负载均衡这套东西——自托管可行。如果你是个小数据团队,主业不是运维数据库——托管服务省下来的时间是实打实的。
  • 阶段三:你已经在运营数据平台了。对大多数团队来说,这时候应该认真考虑托管服务。除非有合规或安全需求要求你必须完全控制数据基础设施。

最有意思的观察是:很多人从阶段一滑进阶段二,从来没有做过明确的决定。 两年过去,突然发现有一个 DuckDB 进程在支撑所有东西,全公司只有一个人知道怎么重启它。

● ● ●

我的看法

这篇文章的好不在于技术深度——三个阶段、四种并发方案都不是新东西。好在透明。

MotherDuck 完全可以只写"我们的托管服务有多好"。但他们选择画一张诚实的地图:告诉你自托管的真实成本,让你自己做决定。这种自信来源于一个判断——当团队真的走到阶段二阶段三,算清楚人员和时间成本后,托管服务的价值就自然浮现了。

对于正在用 DuckDB 的中国团队,这篇文章值得收藏。你不需要现在就做决定,但当你某天发现 import duckdb 变成了 Error: Could not set lock on file,你知道接下来要面对什么。


参考来源:MotherDuck Blog "Self-hosting DuckDB: the road to production" (2026-07-14)

motherduck.com/blog/self-hosting-duckdb-road-to-production