dart_lmdb2
A high-performance, embedded database for Dart applications, wrapping LMDB (Lightning Memory-Mapped Database). This package provides both high-level convenience methods and granular transaction control.
Linux | Windows | Android | MacOS | iOS | web |
---|---|---|---|---|---|
💙 | 💙 | 💙 | 💙 | 💙 | - |
Note: Native binaries must be downloaded before use by running dart run dart_lmdb2:fetch_native
. For iOS/Android you need Flutter to run them on your mobile device. See flutter_lmdb2
Why LMDB?
LMDB is particularly well-suited for mobile and embedded applications because:
-
Mobile-Friendly Design:
- Database format is portable across all platforms
- Battery-efficient through memory mapping and minimal I/O operations
- No background processes or services required
- Predictable memory usage through configurable mapping size
- Instant app startup with lazy data loading
-
Minimal Resource Requirements:
- Ultra-compact native library (<150KB)
- Configurable DB ceiling with fixed mapSize limit
- Single-threaded design with minimal process overhead
- No additional runtime dependencies
-
Exceptional Performance:
- Zero-copy reads through direct memory mapping
- Efficient OS-level page caching eliminates I/O bottlenecks
- Optimized for read operations through direct memory access
- Read transactions never block writers
- Writers never block readers
- Sequential reads are extremely fast due to B+ tree design
-
Reliability:
- Full ACID compliance with atomic, crash-resistant transactions
- Copy-on-write design ensures database integrity even after crashes
- Direct page updates without separate log files
- Optional self-contained single file design simplifies backup operations
- Battle-tested in OpenLDAP
Why not LMDB ?
LMDB is not a general purpose database. It's a DB for specific purposes and shines in these areas.
You should not use LMDB, if
- your schema is not K/V based, but relational
- you need to efficiently query values additionally to keys
- you want to save time series or streaming data (e.g. logging)
- you cannot provide the same amount of RAM as your DB size in write scenarios
Scenarios:
- Super fast querying of big DB's with minimal memory, e.g.
- Dictionaries
- Tile caches
- Texture caching
- Multiplatform assets
- Coherent realtime data updates
- Producer -> Consumer(s)
- Main App -> Plugin Instances
- Audio Engine -> Visualizers
- Multiple Producers -> Multiple Consumers
- Worker Pools
- Distributed Processing
- Resource-Constrained IPC
- Flutter App -> AudioUnit Extension
- Host -> Sandboxed Plugins
- Producer -> Consumer(s)
- Configuration data (and lots of it)
Supported Features
The following LMDB functionality is exposed:
- Complete CRUD operations
- Named databases for data organization
- Cursor operations for range queries
- Full transaction support with ACID guarantees
- Comprehensive statistics and monitoring
- Configurable initialization with all LMDB flags
LMDB Version
This package bundles LMDB version 0.9.70
. While this version number hasn't changed in 3 years, LMDB is actively maintained. We track the exact git repository version: da9aeda.
Getting Started
Add the package to your pubspec.yaml
:
dependencies:
dart_lmdb2: ^0.9.5
Then run:
# For Dart projects:
dart pub get
# For Flutter projects:
flutter pub get
Usage
Import and use:
import 'package:lmdb2/lmdb2.dart';
void main() async {
final db = LMDB();
await db.init('path/to/db');
// Simple auto-transaction operations
await db.putAuto('key', 'value'.codeUnits);
final result = await db.getAuto('key');
// Manual transaction control
final txn = await db.txnStart();
try {
await db.put(txn, 'key1', 'value1'.codeUnits);
await db.put(txn, 'key2', 'value2'.codeUnits);
await db.putUtf8(txn, 'english_greeting', 'Hello World');
await db.txnCommit(txn);
} catch (e) {
await db.txnAbort(txn);
rethrow;
}
}
Configure database settings using LMDBInitConfig
:
final config = LMDBInitConfig(
mapSize: 10 * 1024 * 1024, // 10MB
maxDbs: 1,
envFlags: 0,
mode: 0664,
);
await db.init('path/to/db', config: config);
Native Libraries
Native libraries must be downloaded from GitHub releases before use. They include SHA256 checksum verification for security. Download them by running:
dart run dart_lmdb2:fetch_native
This command downloads libraries to the dart_lmdb2 package directory (not your application directory), ensuring they're in the correct location for FFI loading.
Development
Setting up Git Hooks
To ensure version consistency between pubspec.yaml
and the embedded version, install the git hooks:
./tool/install-hooks.sh
This will install a pre-commit hook that automatically updates lib/src/version.dart
whenever pubspec.yaml
changes. You can verify version consistency at any time:
dart run tool/verify_version.dart
Native Libraries
Native libraries are stored in lib/src/native/
after download:
> tree lib/src/native/
lib/src/native/
├── android
│ ├── arm64-v8a
│ │ └── liblmdb.so
│ └── x86_64
│ └── liblmdb.so
├── ios
│ ├── device
│ │ └── liblmdb.a
│ └── simulator
│ └── liblmdb.a
├── linux
│ └── liblmdb.so
├── macos
│ └── liblmdb.dylib
├── windows
│ └── lmdb.dll
└── manifest.json
You can rebuild these via the following steps:
Prerequisites
This package bundles LMDB to be built from source. The build process is automated but requires:
- CMake (3.10 or higher)
- C compiler (gcc, clang, or MSVC)
- Dart SDK (3.0 or higher)
Platform-specific setup
Android
You need to have installed the Android NDK, ideally via Android Studio. Furthermore. you need to have the environment variable ANDROID_NDK_HOME
set to the appropriate NDK location.
iOS / iPadOS / MacOS
Please install XCode and the XCode command line tools.
# Install build tools
brew install cmake
Linux
# Install build tools
sudo apt-get install build-essential cmake
Windows
- Install Visual Studio with C++ development tools
- Install CMake
Build & Test
- Clone the repository and change to the project subdirectory:
git clone https://github.com/grammatek/dart_lmdb2.git
cd dart_lmdb2/dart_lmdb2
- Install dependencies:
dart pub get
- (Optionally) Rebuild the generated bindings via
ffigen
dart run ffigen
- Build the native library:
dart run tool/build.dart
For Android, you need to pass the flag --android
:
dart run tool/build.dart --android
For iOS/iPadOS, you need to pass the flag --ios
:
dart run tool/build.dart --ios
- Run tests for active platform:
dart test
CREDITS
Many thanks to the OpenLDAP team to provide such a fantastic lightweight, portable and easy to use database. You can access the original source-code either directly as a GitHub standalone version or via the OpenLDAP GitLab repository.
LICENSE
MIT License - see LICENSE file
Libraries
- lmdb
- A high-level Dart interface for LMDB (Lightning Memory-Mapped Database).