打开 lmdb.tech 的文档首页,顶上有一行提示:这是 LMDB 1.0 的文档,0.9 版本的文档已经归档,之前用 0.9 的用户请看专门的升级指南。看上去跟大多数开源项目按部就班的版本迭代没什么两样。
但去查发行证据,事情没那么干净。FreshPorts 上能装到的 LMDB 核心 C 库,最新还是 0.9.35 系列。PyPI 上倒是真有一个叫 lmdb 的 1.0.0,可那是 Python 绑定包 py-lmdb,不是 LMDB 本体。文档标题和实际能装到的软件,对不上号。
LMDB 的老本行没变
先把技术底子摆清楚,这部分文档写得很扎实,值得复述一遍要点:
- 整个数据库直接映射进内存,读数据不用 malloc、不用 memcpy
- B+ 树结构,写时复制(COW),崩溃后不需要专门的恢复流程
- 多版本并发控制让读操作完全无锁,写操作单线程串行,天然不会死锁
- 空闲页自动回收,不像 WAL 或 append-only 方案那样需要定期 compaction
这套设计十几年没大改过,读密集、低延迟的场景一直是它的强项。1.0 文档里重申的这些机制,跟 0.9 时代基本一致,变化更多在文字组织,不在底层行为。
谁会被这个版本号绕进去
真正容易踩坑的是两类人。一类是拿 LMDB 做底层存储的项目——OpenLDAP、区块链客户端、消息中间件——如果照着 1.0 文档里的说法去规划升级,却发现能装到的还是 0.9.35,特性对不上就得回头核实。另一类是用 Python 绑定 py-lmdb 的开发者,看到 pip 装出来是 1.0.0,容易顺手把这个版本号当成 LMDB 核心引擎的版本,实际上两者编号完全独立。
- 风险.按文档里的1.0特性写代码,却部署的是0.9.35的库,版本预期和实际行为可能对不上。
值得一提的是,OpenLDAP 社区确实有讨论面向 1.0 的具体功能(比如子树排序支持),说明 1.0 不是空标题,而是有真实规划在推进。但规划和正式发布之间,还隔着一个 changelog、一个 tag。文档先走一步,库还没跟上,这在开源世界不算新鲜事,只是这次的落差被包管理器数据坐实了。
文档写的是终点,发行证据停在半路。
老运维坑还在,选型看场景
版本号之争之外,LMDB 那些长期存在的运维痛点,并没有因为文档改名就消失。stale reader 阻塞空闲页回收、数据库跟着膨胀,lockfile 权限出问题导致多进程协调失败——这些是 0.9 时代就写在文档里的坑,1.0 文档原样保留,说明它们还是要靠运维自己规避,不是版本升级能解决的。
场景选型上,LMDB 的优势边界其实很清楚。读密集、需要低延迟、不想维护 compaction 的场景,LMDB 的单写者串行模型够用;写密集、高并发写入的场景,RocosDB 这类 LSM 树方案吞吐更高,这也是它们在服务器端 flash 存储的 IO 密集测试里表现更好的原因。如果需要 SQL,那是 SQLite 的地盘,它的 mmap 优化本身也只帮读,不帮写。
- 结论.选型前别只看文档标题,去包管理器和源码仓库交叉核实发行状态,再决定要不要按1.0的说法写代码。
