← На главную

LMDB: встраиваемая БД на B-деревьях — проблемы от lockfile и долгих транзакций

02.07.2026 20:01 · hackernews

LMDB — это встраиваемая библиотека управления базами данных на B-деревьях. Она построена на идее memory map: вся база отображается в память, и данные отдаются напрямую оттуда — без malloc и memcpy. Никакого собственного слоя кэширования не нужно. Отсюда высокая производительность и эффективное использование памяти.

Библиотека полностью транзакционна — с полноценной ACID-семантикой. Если использовать memory map только для чтения, целостность базы не нарушится даже при случайной записи по указателю из приложения. LMDB поддерживает конкурентный доступ из нескольких потоков и процессов. Страницы данных используют copy-on-write: активные страницы никогда не перезаписываются, поэтому сбои системы не требуют специального восстановления. Записи полностью сериализованы — только одна write-транзакция может быть активна в момент времени, что исключает deadlock. База данных мультиверсионна: читатели работают без блокировок, писатели не блокируют читателей и наоборот.

В отличие от механизмов с write-ahead log или append-only, LMDB не требует обслуживания во время работы — логи и компактизация не нужны. Свободные страницы внутри базы автоматически переиспользуются, поэтому размер файла не растёт бесконечно.

По умолчанию memory map используется в режиме read-only — это защищает от повреждений. Режим read-write даёт гораздо более высокую скорость записи, но добавляет риск случайного повреждения базы через указатели из приложения (если в коде есть баги).

Битая lockfile может вызывать проблемы синхронизации. Старые reader-транзакции, оставленные аварийно завершённой программой, заставляют базу быстро расти. На большинстве систем writer'ы очищаются автоматически (Windows, BSD с SysV semaphores, Linux с Robust POSIX mutexes). На BSD или системах с MDB_USE_POSIX_SEM запуск может провалиться из-за семафоров, принадлежащих другому пользователю — помогает открыть и закрыть базу от владельца семафоров.

Чистого read-only режима обычно нет — читателям нужен доступ к блокировкам. Исключение — read-only файловые системы или флаг MDB_NOLOCK. При настройке LMDB часто резервирует большой неиспользуемый адресный пространство и размер файла под будущий рост — это не занимает реальной памяти или диска.

До версии 0.9.10 неиспользуемые части файла могли содержать мусор; начиная с 0.9.10 память инициализируется перед записью (можно отключить флагом MDB_NOMEMINIT, но не для чувствительных данных). Один поток может использовать только одну транзакцию + дочерние. Нельзя открывать LMDB дважды в одном процессе — закрытие ломает fcntl() advisory locking. Долгоживущие транзакции ведут к быстрому росту базы. Нельзя использовать LMDB на удалённых файловых системах. И нельзя прерывать процесс с активными транзакциями — они становятся «долгоживущими» до проверки stale readers или сброса lockfile.

Автор библиотеки — Howard Chu, Symas Corporation.

Читать оригинал →