lmdb clib

Lightning Memory-Mapped Database — embedded key-value store with ACID transactions, zero-copy reads, and sorted cursor iteration.

ppm install lmdb
Requires liblmdb-dev on Ubuntu/Debian: sudo apt install liblmdb-dev

Overview

Memory-mappedReads are zero-copy — as fast as a pointer dereference. No buffer copies.
MVCC transactionsACID with Multi-Version Concurrency Control. Readers never block writers.
Single fileNo log files, no write-ahead log, no recovery needed. Simple to deploy.
Sorted keysKeys always stored in binary order. Range scans are O(log n) + sequential.
Read throughputMillions of reads/sec — used by OpenLDAP, Mozilla, Bitcoin Core, Tor.
Named sub-databasesMultiple key-value spaces (DBI) within one environment file.

Quick Start

uses lmdb;

{ Open environment — 100 MB map, 4 named sub-databases }
var env := EnvOpen('/tmp/mydb', 100 * 1024 * 1024, 4, 126);

{ Write transaction }
var txn := TxnBegin(env);
var dbi := DBIOpen(txn);        { default unnamed DB }

Put(txn, dbi, 'hello', 'world');
Put(txn, dbi, 'foo',   'bar');
TxnCommit(txn);

{ Read transaction }
var ro := TxnBeginRO(env);
var v  := Get(ro, dbi, 'hello');  { 'world' }
TxnAbort(ro);

EnvClose(env);

Named Sub-Databases

var env := EnvOpen('/tmp/app', 512 * 1024 * 1024, 8, 126);
var txn := TxnBegin(env);

var users    := DBIOpenNamed(txn, 'users');
var sessions := DBIOpenNamed(txn, 'sessions');

Put(txn, users,    'u:1001', '{"name":"Alice"}');
Put(txn, sessions, 's:abc123', 'u:1001');
TxnCommit(txn);

Cursor Iteration

var ro  := TxnBeginRO(env);
var cur := CursorOpen(ro, dbi);

{ Iterate all keys in sorted order }
if CursorFirst(cur) then
repeat
  Writeln(CursorKey(cur) + ' = ' + CursorValue(cur));
until not CursorNext(cur);

{ Range scan: keys starting with 'user:' }
if CursorSeekRange(cur, 'user:') then
repeat
  if not StartsWith(CursorKey(cur), 'user:') then break;
  Writeln(CursorKey(cur));
until not CursorNext(cur);

CursorClose(cur);
TxnAbort(ro);

Hot Backup

{ Copy the live environment to another path — no downtime }
EnvCopy(env, '/backup/mydb');

{ Get environment info }
var info := EnvInfo(env);
Writeln('Map size: ' + IntToStr(info.MapSize));
Writeln('Readers: '  + IntToStr(info.NumReaders));

API Reference

Environment

FunctionDescription
EnvOpen(Path, MapSize, MaxDBs, MaxReaders)Open or create an LMDB environment. MapSize in bytes (can exceed RAM).
EnvOpenReadOnly(Path, MapSize)Open read-only environment.
EnvClose(Env)Close environment and release the memory map.
EnvSetMapSize(Env, MapSize)Resize the map (no open transactions allowed).
EnvSync(Env, Force)Flush buffers to disk.
EnvInfo(Env)Returns TLMDBInfo: MapSize, LastPageNo, MaxReaders, NumReaders.
EnvCopy(Env, Path)Hot-copy the live environment to a directory.

Transactions

FunctionDescription
TxnBegin(Env)Begin a read-write transaction.
TxnBeginRO(Env)Begin a read-only transaction (multiple can run concurrently).
TxnCommit(Txn)Commit the transaction.
TxnAbort(Txn)Abort/rollback the transaction.
TxnReset(Txn)Reset a read-only transaction for reuse.
TxnRenew(Txn)Renew a previously reset read-only transaction.

Database (DBI)

FunctionDescription
DBIOpen(Txn)Open the default unnamed database.
DBIOpenNamed(Txn, Name)Open a named sub-database (created if it doesn't exist).
DBIClose(Env, DBI)Close a DBI handle (rarely needed).
DBIDrop(Txn, DBI, DeleteDB)Clear all entries or delete the sub-database entirely.
DBIStat(Txn, DBI)Returns TLMDBStat: Entries, Depth, PageSize, LeafPages.

Read / Write

FunctionDescription
Get(Txn, DBI, Key)Get value for a key. Returns '' if not found.
Exists(Txn, DBI, Key)Return True if the key exists.
Put(Txn, DBI, Key, Value)Insert or replace a key-value pair.
PutNoOverwrite(Txn, DBI, Key, Value)Insert only if key doesn't exist. Returns False if it does.
Delete(Txn, DBI, Key)Delete a key. Returns False if not found.

Cursor

FunctionDescription
CursorOpen(Txn, DBI)Open a cursor for sorted iteration.
CursorClose(Cursor)Close and free the cursor.
CursorFirst/Last(Cursor)Move to first or last key. Returns False if empty.
CursorNext/Prev(Cursor)Move to next or previous key.
CursorSeek(Cursor, Key)Seek to exact key match. Returns False if not found.
CursorSeekRange(Cursor, Key)Seek to first key >= Key (range scan start).
CursorKey/Value(Cursor)Get current key or value.
CursorPut(Cursor, Key, Value)Write at cursor position.
CursorDelete(Cursor)Delete the entry at cursor position.