2025年还在用SQLite做生产存储,很多人第一反应是"你们是不是没预算上正经数据库"。但我这几年在真实项目里反复用SQLite踩坑、调优、扛流量之后,必须说一句:SQLite在生产环境的适应能力,被严重低估了。它绝不是只能存本地配置的小玩具,很多看起来"应该上MySQL/PG"的场景,其实用SQLite反而是更合理的架构决策。这篇文章不打算复述官方文档,而是以我和团队实际维护过的生产系统为蓝本,把我评估选型、参数调优、问题排障、容器化部署、备份恢复整套经验一次性讲透。
1. 先泼盆冷水再给答案:SQLite不是"看不起的玩具库"
先聊聊我为什么会在一套正式业务系统里选择SQLite。那是一个边缘侧的本地调度服务,单机部署,资源预算非常有限,整个机器只有2核4G,还需要跑好几个业务进程。业务方最初坚持要上MySQL,理由是"生产环境怎么能用SQLite"。后来我把需求拆开看:最大并发连接数不超过10,90%的流量是读状态,写入基本是单线程的定时落库,数据总量一年撑死几十GB。这种负载之下,MySQL集群不仅浪费资源,还带来了主从同步、账号权限、连接池管理等一堆本不需要存在的运维成本。于是我们改用SQLite,上线后CPU和内存占用几乎可以忽略。
我举这个例子不是要说MySQL不行,而是提醒大家:生产环境选型的第一原则不是"别人都用什么",而是"这个场景真正需要什么"。SQLite是嵌入式关系型数据库,它把整个数据库引擎作为库文件直接链进应用进程,不需要独立的数据库服务进程,不需要监听端口,不需要专门的DBA维护实例。这个特性决定了它在单机、低并发、数据量可控但逻辑关系复杂的场景里,起手就比客户端/服务端架构的数据库少了一大截开销。
作为选型负责人,我一般从四个维度判断SQLite能不能上生产:
| 判断维度 | 适合使用SQLite | 不建议使用SQLite |
|---|---|---|
| 并发模型 | 多读少写,写操作能控制在单点串行 | 大量并发写,需要行级并发写入 |
| 部署方式 | 单机部署,无多节点横向扩展诉求 | 多实例共享同一份数据文件 |
| 数据规模 | 单库几十GB以内,单表千万行量级 | 单表上亿行,需要分布式分片 |
| 团队运维能力 | 希望降低运维复杂度,尽量零依赖 | 已经有成熟的数据库运维体系,且明确要求主从高可用 |
有一点需要强调:选SQLite不能是"为了方便省事"的偷懒,而应当是经过负载评估后确认它恰好落在能力范围之内的决策。如果一个系统明确预测未来的写TPS会持续超过SQLite单文件的处理能力,或者需要多台应用服务器同时直连同一个库,那还是老老实实上专用数据库,不要硬扛。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 生产选型前,把这几个能力边界算清楚
我在评审技术方案时最不喜欢听到一句话:"先用SQLite顶一下,不行再迁移。"数据库迁移从来不是低成本的事。所以必须在项目启动前对SQLite的能力边界做一次完整推演。以下这几个点,决定了它能不能在你的生产场景里站稳。
2.1 并发模型:SQLite实际上锁的是什么
SQLite传统的锁机制是整库级别的读写锁。未开启WAL模式时,读会阻塞写,写也会阻塞读,这种"一夫一妻"式的互斥基本适应不了真实业务。生产环境使用SQLite几乎必须打开WAL(Write-Ahead Logging)模式。WAL模式下,读事务和写事务可以在一定程度上并行:写操作只会追加到wal文件,读操作继续从原来的数据库文件读取快照,因此读不会阻塞写,写也不会阻塞读。
但是要注意,WAL并没有把SQLite变成多写并发数据库。写入仍然是全局串行化的,同一时刻只允许一个写事务提交。所以评估一个场景能不能用SQLite,核心不是看并发连接数,而是看"写入吞吐需求"和"写入冲突概率"。如果一个瞬间有几十个请求同时尝试写入,虽然WAL允许进程间的读并发,但写锁只有一个,后面的写请求如果超过busy_timeout还没有等到锁,就会直接返回SQLITE_BUSY。
我通常用一个非常粗的公式估算写入压力:单条写事务耗时约0.1到几毫秒(取决于数据量和磁盘),再留出50%的余量,推算出单库每秒大约能完成多少写事务。这个数字不需要很精确,因为决定吞吐上限的往往是磁盘fsync频率,而不是CPU。只要评估结果距离未来峰值流量还有3到5倍余量,SQLite基本就没问题。
2.2 事务与持久性:不是崩溃后一定丢数据
很多人对SQLite持久性的印象还停留在"PRAGMA synchronous=OFF,一断电就丢数据"。实际上SQLite的可靠性是可以按需配置的。默认的DELETE模式加synchronous=FULL,每提交一个事务都要把数据刷到磁盘,安全性相当高。在WAL模式下把synchronous调整为NORMAL,只保证在操作系统崩溃时可能丢失最近少量提交事务,但在应用崩溃或者断电场景下数据库文件本身不会损坏。反过来,如果误把synchronous设成OFF,那系统断电或者进程被kill -9的瞬间,确实可能丢数据甚至损坏库文件。所以不是SQLite不持久,而是你必须知道自己设置到了哪一档。
这部分在生产环境配置上有个我常用的组合:journal_mode=WAL,synchronous=NORMAL,busy_timeout=5000。这个组合兼顾并发性能与安全性,适合绝大多数单机生产服务。只有当写操作本身要求极其严苛的"不丢任何已提交事务"时,才会把synchronous升到FULL。注意,升级到FULL会让每次提交都等待落盘,写吞吐会明显下降,要在业务上判断能不能接受。
2.3 多进程还是单进程多连接
很多新手会混淆"SQLite支持多线程"和"SQLite支持多进程同时打开同一个库"。这两件事都支持,但使用条件不一样。SQLite本身是线程安全的,前提是编译参数开启了THREADSAFE,而且同一个连接不能同时被多个线程无保护地使用。大多
