自托管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