mirror of
https://github.com/isar/libmdbx.git
synced 2024-12-30 01:34:14 +08:00
mdbx: refine README.
This commit is contained in:
parent
ad7113419b
commit
c4142c9a35
399
README.md
399
README.md
@ -6,71 +6,81 @@ Extended LMDB, aka "Расширенная LMDB".
|
||||
|
||||
[![Build Status](https://travis-ci.org/ReOpen/libmdbx.svg?branch=devel)](https://travis-ci.org/ReOpen/libmdbx)
|
||||
|
||||
English version by Google [is
|
||||
here](https://translate.googleusercontent.com/translate_c?act=url&depth=1&hl=ru&ie=UTF8&prev=_t&rurl=translate.google.com&sl=ru&tl=en&u=https://github.com/ReOpen/libmdbx/tree/devel).
|
||||
|
||||
English version by Google [is here](https://translate.googleusercontent.com/translate_c?act=url&depth=1&hl=ru&ie=UTF8&prev=_t&rurl=translate.google.com&sl=ru&tl=en&u=https://github.com/ReOpen/libmdbx/tree/devel).
|
||||
|
||||
|
||||
## Кратко
|
||||
libmdbx - это встраиваемый key-value движок хранения со специфическим
|
||||
набором возможностей, которые при правильном применении позволяют создавать
|
||||
уникальные решения с чемпионской производительностью.
|
||||
_libmdbx_ - это встраиваемый key-value движок хранения со
|
||||
специфическим набором возможностей, которые при правильном
|
||||
применении позволяют создавать уникальные решения с чемпионской
|
||||
производительностью, идеально сочетаясь с технологией
|
||||
[MRAM](https://en.wikipedia.org/wiki/Magnetoresistive_random-access_memory).
|
||||
|
||||
libmdbx является форком [Symas Lightning Memory-Mapped
|
||||
Database](https://symas.com/products/lightning-memory-mapped-database/)
|
||||
(известной под аббревиатурой
|
||||
[LMDB](https://en.wikipedia.org/wiki/Lightning_Memory-Mapped_Database)), с
|
||||
рядом существенных доработок, которые перечислены ниже.
|
||||
_libmdbx_ обновляет совместно используемый набор данных, никак
|
||||
не мешая при этом параллельным операциям чтения, не применяя
|
||||
атомарных операций к самим данным, и обеспечивая
|
||||
согласованность при аварийной остановке в любой момент. Поэтому
|
||||
_libmdbx_ позволяя строить системы с линейным масштабированием
|
||||
производительности чтения/поиска по ядрам CPU и амортизационной
|
||||
стоимостью любых операций Olog(N).
|
||||
|
||||
Изначально модификация производилась в составе исходного кода проекта
|
||||
[ReOpenLDAP](https://github.com/ReOpen/ReOpenLDAP). Примерно за год работы
|
||||
внесенные изменения приобрели самостоятельную ценность.
|
||||
|
||||
Осенью 2015 доработанный движок был выделен в отдельный проект, который был
|
||||
[представлен на конференции Highload++
|
||||
2015](http://www.highload.ru/2015/abstracts/1831.html).
|
||||
### История
|
||||
_libmdbx_ является потомком "Lightning Memory-Mapped Database",
|
||||
известной под аббревиатурой
|
||||
[LMDB](https://en.wikipedia.org/wiki/Lightning_Memory-Mapped_Database).
|
||||
Изначально доработка производилась в составе проекта
|
||||
[ReOpenLDAP](https://github.com/ReOpen/ReOpenLDAP). Примерно за
|
||||
год работы внесенные изменения приобрели самостоятельную
|
||||
ценность. Осенью 2015 доработанный движок был выделен в
|
||||
отдельный проект, который был [представлен на конференции
|
||||
Highload++ 2015](http://www.highload.ru/2015/abstracts/1831.html).
|
||||
|
||||
|
||||
## Характеристики и ключевые особенности
|
||||
Характеристики и ключевые особенности
|
||||
=====================================
|
||||
|
||||
### Общее для оригинальной LMDB и MDBX
|
||||
_libmdbx_ наследует все ключевые возможности и особенности от
|
||||
своего прародителя [LMDB](https://en.wikipedia.org/wiki/Lightning_Memory-Mapped_Database),
|
||||
с устранением описанных далее проблем и архитектурных недочетов.
|
||||
|
||||
* Данные хранятся в упорядоченном отображении (ordered map), ключи всегда
|
||||
отсортированы, поддерживается выборка диапазонов (range lookups).
|
||||
### Общее для оригинальной _LMDB_ и _libmdbx_
|
||||
|
||||
* Транзакции согласно [ACID](https://ru.wikipedia.org/wiki/ACID), посредством
|
||||
[MVCC](https://ru.wikipedia.org/wiki/MVCC)
|
||||
и [COW](https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BF%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%BF%D1%80%D0%B8_%D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D0%B8).
|
||||
1. Данные хранятся в упорядоченном отображении (ordered map), ключи всегда
|
||||
отсортированы, поддерживается выборка диапазонов (range lookups).
|
||||
|
||||
* Чтение [без
|
||||
блокировок](https://ru.wikipedia.org/wiki/%D0%9D%D0%B5%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D1%83%D1%8E%D1%89%D0%B0%D1%8F_%D1%81%D0%B8%D0%BD%D1%85%D1%80%D0%BE%D0%BD%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F),
|
||||
без [атомарных операций](https://ru.wikipedia.org/wiki/%D0%90%D1%82%D0%BE%D0%BC%D0%B0%D1%80%D0%BD%D0%B0%D1%8F_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D1%8F).
|
||||
Мьютексы захватываются только при старте и завершении сеанса работы с БД.
|
||||
2. Данные отображается в память каждого работающего с БД процесса.
|
||||
Ключам и данным обеспечивается прямой доступ без необходимости их
|
||||
копирования, так как они защищены транзакцией чтения и не изменяются.
|
||||
|
||||
* Читатели не конкурируют между собой, чтение масштабируется линейно по ядрам CPU.
|
||||
3. Транзакции согласно
|
||||
[ACID](https://ru.wikipedia.org/wiki/ACID), посредством
|
||||
[MVCC](https://ru.wikipedia.org/wiki/MVCC) и
|
||||
[COW](https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BF%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%BF%D1%80%D0%B8_%D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D0%B8).
|
||||
Изменения строго последовательны и не блокируются чтением,
|
||||
конфликты между транзакциями не возможны.
|
||||
|
||||
* Изменения строго последовательны и не блокируются чтением, конфликты между
|
||||
транзакциями не возможны.
|
||||
4. Чтение и поиск [без блокировок](https://ru.wikipedia.org/wiki/%D0%9D%D0%B5%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D1%83%D1%8E%D1%89%D0%B0%D1%8F_%D1%81%D0%B8%D0%BD%D1%85%D1%80%D0%BE%D0%BD%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F),
|
||||
без [атомарных операций](https://ru.wikipedia.org/wiki/%D0%90%D1%82%D0%BE%D0%BC%D0%B0%D1%80%D0%BD%D0%B0%D1%8F_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D1%8F).
|
||||
Читатели не блокируются операциями записи и не конкурируют
|
||||
между собой, чтение масштабируется линейно по ядрам CPU.
|
||||
|
||||
* Амортизационная стоимость любой операции Olog(N),
|
||||
[WAF](https://en.wikipedia.org/wiki/Write_amplification) и RAF также Olog(N).
|
||||
5. Эффективное хранение дубликатов (ключей с несколькими
|
||||
значениями), без дублирования ключей, с сортировкой значений, в
|
||||
том числе целочисленных (для вторичных индексов).
|
||||
|
||||
* Нет [WAL](https://en.wikipedia.org/wiki/Write-ahead_logging) и журнала
|
||||
транзакций, после сбоев не требуется восстановление.
|
||||
6. Эффективная поддержка ключей фиксированной длины, в том числе целочисленных.
|
||||
|
||||
* Не требуется компактификация или какое-либо периодическое обслуживание.
|
||||
7. Амортизационная стоимость любой операции Olog(N),
|
||||
[WAF](https://en.wikipedia.org/wiki/Write_amplification) и RAF также Olog(N).
|
||||
|
||||
* Эффективное хранение дубликатов (ключей с несколькими значениями) с
|
||||
сортировкой значений.
|
||||
8. Нет [WAL](https://en.wikipedia.org/wiki/Write-ahead_logging) и журнала
|
||||
транзакций, после сбоев не требуется восстановление. Не требуется компактификация
|
||||
или какое-либо периодическое обслуживание. Поддерживается резервное копирование
|
||||
"по горячему", на работающей БД без приостановки изменения данных.
|
||||
|
||||
* Эффективная поддержка ключей фиксированной длины (uint32_t, uint64_t).
|
||||
|
||||
* Поддержка горячего резервного копирования.
|
||||
|
||||
* Файл БД отображается в память кажлого процесса, который работает с БД. К
|
||||
ключам и данным обеспечивается прямой доступ (без копирования), они не
|
||||
меняются до завершения транзакции чтения.
|
||||
|
||||
* Отсутствует какое-либо внутреннее управление памятью или кэшированием. Всё
|
||||
необходимое выполняет ядро ОС.
|
||||
9. Отсутствует какое-либо внутреннее управление памятью или кэшированием. Всё
|
||||
необходимое штатно выполняет ядро ОС.
|
||||
|
||||
|
||||
### Недостатки и Компромиссы
|
||||
@ -82,9 +92,9 @@ Database](https://symas.com/products/lightning-memory-mapped-database/)
|
||||
2. Отсутствие [WAL](https://en.wikipedia.org/wiki/Write-ahead_logging)
|
||||
обуславливает относительно большой
|
||||
[WAF](https://en.wikipedia.org/wiki/Write_amplification). Поэтому фиксация
|
||||
изменений на диске относительно дорога и является главным ограничителем для
|
||||
изменений на диске может быть дорогой и является главным ограничителем для
|
||||
производительности по записи. В качестве компромисса предлагается несколько
|
||||
режимов ленивой и/или периодической фиксации. В том числе режим `WRITEMAP`,
|
||||
режимов ленивой и/или периодической фиксации. В том числе режим `MAPASYNC`,
|
||||
при котором изменения происходят только в памяти и асинхронно фиксируются на
|
||||
диске ядром ОС.
|
||||
|
||||
@ -94,173 +104,228 @@ Database](https://symas.com/products/lightning-memory-mapped-database/)
|
||||
Поэтому изменение данных амортизационно требует копирования Olog(N) страниц,
|
||||
что расходует [пропускную способность оперативной
|
||||
памяти](https://en.wikipedia.org/wiki/Memory_bandwidth) и является основным
|
||||
ограничителем производительности в режиме `WRITEMAP`.
|
||||
ограничителем производительности в режиме `MAPASYNC`.
|
||||
|
||||
4. Проблема долгих чтений (зависших читателей), см. ниже.
|
||||
4. В _LMDB_ существует проблема долгих чтений (приостановленных читателей),
|
||||
которая приводит к деградации производительности и переполнению БД.
|
||||
В _libmdbx_ предложены средства для предотвращения, выхода из проблемной
|
||||
ситуации и устранения её последствий. Подробности ниже.
|
||||
|
||||
5. Вероятность разрушения БД в режиме `WRITEMAP`, см ниже.
|
||||
5. В _LMDB_ есть вероятность разрушения БД в режиме `WRITEMAP+MAPASYNC`.
|
||||
В _libmdbx_ для `WRITEMAP+MAPASYNC` гарантируется как сохранность базы,
|
||||
так и согласованность данных. При этом также, в качестве альтернативы,
|
||||
предложен режим `UTTERLY_NOSYNC`. Подробности ниже.
|
||||
|
||||
|
||||
#### Проблема долгих чтений
|
||||
|
||||
Понимание проблемы требует некоторых пояснений, которые изложены ниже, но
|
||||
могут быть сложны для быстрого восприятия. Поэтому, тезисно:
|
||||
Понимание проблемы требует некоторых пояснений, которые
|
||||
изложены ниже, но могут быть сложны для быстрого восприятия.
|
||||
Поэтому, тезисно:
|
||||
|
||||
* Изменение данных на фоне долгой операции чтения может приводить к исчерпанию
|
||||
места в БД.
|
||||
* Изменение данных на фоне долгой операции чтения может
|
||||
приводить к исчерпанию места в БД.
|
||||
|
||||
* После чего любая попытка обновить данные будет приводить к ошибке `MAP_FULL`
|
||||
до завершения долгой операции чтения.
|
||||
* После чего любая попытка обновить данные будет приводить к
|
||||
ошибке `MAP_FULL` до завершения долгой операции чтения.
|
||||
|
||||
* Характерными примерами долгих чтений являются горячее резервное копирования
|
||||
и отладка клиентского приложения при активной транзакции чтения.
|
||||
* Характерными примерами долгих чтений являются горячее
|
||||
резервное копирования и отладка клиентского приложения при
|
||||
активной транзакции чтения.
|
||||
|
||||
* В оригинальной LMDB после этого будет наблюдаться устойчивая деградация
|
||||
производительности всех механизмов обратной записи на диск (в I/O контроллере,
|
||||
в гипервизоре, в ядре ОС).
|
||||
* В оригинальной _LMDB_ после этого будет наблюдаться
|
||||
устойчивая деградация производительности всех механизмов
|
||||
обратной записи на диск (в I/O контроллере, в гипервизоре,
|
||||
в ядре ОС).
|
||||
|
||||
* В MDBX предусмотрен механизм аварийного прерывания таких операций, а также
|
||||
режим `LIFO RECLAIM` устраняющий последующую деградацию производительности.
|
||||
* В _libmdbx_ предусмотрен механизм аварийного прерывания таких
|
||||
операций, а также режим `LIFO RECLAIM` устраняющий последующую
|
||||
деградацию производительности.
|
||||
|
||||
Операции чтения выполняются в контексте снимка данных (версии БД), который был
|
||||
актуальным на момент старта транзакции чтения. Такой читаемый снимок
|
||||
поддерживается неизменным до завершения операции. В свою очередь, это не
|
||||
позволяет повторно использовать страницы БД в последующих версиях (снимках
|
||||
БД).
|
||||
Операции чтения выполняются в контексте снимка данных (версии
|
||||
БД), который был актуальным на момент старта транзакции чтения.
|
||||
Такой читаемый снимок поддерживается неизменным до завершения
|
||||
операции. В свою очередь, это не позволяет повторно
|
||||
использовать страницы БД в последующих версиях (снимках БД).
|
||||
|
||||
Другими словами, если обновление данных выполняется на фоне долгой операции
|
||||
чтения, то вместо повторного использования "старых" ненужных страниц будут
|
||||
выделяться новые, так как "старые" страницы составляют снимок БД, который еще
|
||||
Другими словами, если обновление данных выполняется на фоне
|
||||
долгой операции чтения, то вместо повторного использования
|
||||
"старых" ненужных страниц будут выделяться новые, так как
|
||||
"старые" страницы составляют снимок БД, который еще
|
||||
используется долгой операцией чтения.
|
||||
|
||||
В результате, при интенсивном изменении данных и достаточно длительной
|
||||
операции чтения, в БД могут быть исчерпаны свободные страницы, что не позволит
|
||||
создавать новые снимки/версии БД. Такая ситуация будет сохраняться до
|
||||
завершения операции чтения, которая использует старый снимок данных и
|
||||
препятствует повторному использованию страниц БД.
|
||||
В результате, при интенсивном изменении данных и достаточно
|
||||
длительной операции чтения, в БД могут быть исчерпаны свободные
|
||||
страницы, что не позволит создавать новые снимки/версии БД.
|
||||
Такая ситуация будет сохраняться до завершения операции чтения,
|
||||
которая использует старый снимок данных и препятствует
|
||||
повторному использованию страниц БД.
|
||||
|
||||
Однако, на этом проблемы не заканчиваются. После описанной ситуации, все
|
||||
дополнительные страницы, которые были выделены пока переработка старых была
|
||||
невозможна, будут участвовать в цикле выделения/освобождения до конца жизни
|
||||
экземпляра БД. В оригинальной LMDB этот цикл использования страниц работает по
|
||||
принципу [FIFO](https://ru.wikipedia.org/wiki/FIFO). Поэтому увеличение
|
||||
количества циркулирующий страниц, с точки зрения механизмов кэширования и/или
|
||||
обратной записи, выглядит как увеличение рабочего набор данных. Проще говоря,
|
||||
однократное попадание в ситуацию "уснувшего читателя" приводит к устойчивому
|
||||
эффекту вымывания I/O кэша при всех последующих изменениях данных.
|
||||
Однако, на этом проблемы не заканчиваются. После описанной
|
||||
ситуации, все дополнительные страницы, которые были выделены
|
||||
пока переработка старых была невозможна, будут участвовать в
|
||||
цикле выделения/освобождения до конца жизни экземпляра БД. В
|
||||
оригинальной _LMDB_ этот цикл использования страниц работает по
|
||||
принципу [FIFO](https://ru.wikipedia.org/wiki/FIFO). Поэтому
|
||||
увеличение количества циркулирующий страниц, с точки зрения
|
||||
механизмов кэширования и/или обратной записи, выглядит как
|
||||
увеличение рабочего набор данных. Проще говоря, однократное
|
||||
попадание в ситуацию "уснувшего читателя" приводит к
|
||||
устойчивому эффекту вымывания I/O кэша при всех последующих
|
||||
изменениях данных.
|
||||
|
||||
Для решения описанных проблемы в MDBX сделаны существенные доработки, см.
|
||||
ниже. Иллюстрации к проблеме "долгих чтений" можно найти в [слайдах
|
||||
презентации](http://www.slideshare.net/leoyuriev/lmdb). Там же приведен пример
|
||||
количественной оценки прироста производительности за счет эффективной работы
|
||||
[BBWC](https://en.wikipedia.org/wiki/BBWC) при включении `LIFO RECLAIM` в
|
||||
MDBX.
|
||||
Для устранения описанных проблемы в _libmdbx_ сделаны
|
||||
существенные доработки, подробности ниже. Иллюстрации к
|
||||
проблеме "долгих чтений" можно найти в [слайдах
|
||||
презентации](http://www.slideshare.net/leoyuriev/lmdb).
|
||||
Там же приведен пример количественной оценки прироста
|
||||
производительности за счет эффективной работы
|
||||
[BBWC](https://en.wikipedia.org/wiki/BBWC) при включении `LIFO
|
||||
RECLAIM` в _libmdbx_.
|
||||
|
||||
|
||||
## Доработки MDBX
|
||||
#### Вероятность разрушения БД в режиме `WRITEMAP+MAPASYNC`
|
||||
|
||||
При работе в режиме `WRITEMAP+MAPSYNC` запись измененных
|
||||
страниц выполняется ядром ОС, что имеет ряд преимуществ. Так
|
||||
например, при крахе приложения, ядро ОС сохранит все изменения.
|
||||
|
||||
Однако, при аварийном отключении питания или сбое в ядре ОС, на
|
||||
диске будет сохранена только часть измененных страниц БД. При
|
||||
этом с большой вероятностью может оказаться так, что будут
|
||||
сохранены мета-страницы со ссылками на страницы с новыми
|
||||
версиями данных, но не сами новые данные. В этом случае БД
|
||||
будет безвозвратна разрушена, даже если до аварии производилась
|
||||
полная синхронизация данных (посредством `mdb_env_sync()`).
|
||||
|
||||
В _libmdbx_ эта проблема устранена, подробности ниже.
|
||||
|
||||
|
||||
Доработки _libmdbx_
|
||||
===================
|
||||
|
||||
1. Режим `LIFO RECLAIM`.
|
||||
|
||||
Для повторного использования выбираются не самые старые, а самые новые
|
||||
страницы из доступных. За счет этого цикл использования страниц всегда
|
||||
имеет минимальную длину и не зависит от общего числа выделенных страниц.
|
||||
Для повторного использования выбираются не самые старые, а
|
||||
самые новые страницы из доступных. За счет этого цикл
|
||||
использования страниц всегда имеет минимальную длину и не
|
||||
зависит от общего числа выделенных страниц.
|
||||
|
||||
В результате механизмы кэширования и обратной записи работают с
|
||||
максимально возможной эффективностью. В случае использования контроллера
|
||||
дисков или системы хранения с [BBWC](https://en.wikipedia.org/wiki/BBWC)
|
||||
возможно многократное увеличение производительности по записи
|
||||
(обновлению данных).
|
||||
В результате механизмы кэширования и обратной записи работают с
|
||||
максимально возможной эффективностью. В случае использования
|
||||
контроллера дисков или системы хранения с
|
||||
[BBWC](https://en.wikipedia.org/wiki/BBWC) возможно
|
||||
многократное увеличение производительности по записи
|
||||
(обновлению данных).
|
||||
|
||||
2. Обработчик `OOM-KICK`.
|
||||
|
||||
Посредством `mdbx_env_set_oomfunc()` может быть
|
||||
установлен внешний обработчик (callback), который будет вызван при исчерпания
|
||||
свободных страниц из-за долгой операцией чтения. Обработчику будет передан PID
|
||||
и pthread_id. В свою очередь обработчик может предпринять одно из действий:
|
||||
Посредством `mdbx_env_set_oomfunc()` может быть установлен
|
||||
внешний обработчик (callback), который будет вызван при
|
||||
исчерпания свободных страниц из-за долгой операцией чтения.
|
||||
Обработчику будет передан PID и pthread_id. В свою очередь
|
||||
обработчик может предпринять одно из действий:
|
||||
|
||||
* отправить сигнал kill (#9), если долгое чтение выполняется сторонним процессом;
|
||||
* отменить или перезапустить проблемную операцию чтения, если операция
|
||||
выполняется одним из потоков текущего процесса;
|
||||
* подождать некоторое время, в расчете что проблемная операция чтения будет
|
||||
штатно завершена;
|
||||
* перервать текущую операцию изменения данных с возвратом кода ошибки.
|
||||
* отправить сигнал kill (#9), если долгое чтение выполняется
|
||||
сторонним процессом;
|
||||
|
||||
3. Гарантия сохранности БД в режиме `WRITEMAP`.
|
||||
* отменить или перезапустить проблемную операцию чтения, если
|
||||
операция выполняется одним из потоков текущего процесса;
|
||||
|
||||
При работе в режиме `WRITEMAP` запись измененных страниц выполняется ядром ОС,
|
||||
что имеет ряд преимуществ. Так например, при крахе приложения, ядро ОС
|
||||
сохранит все изменения.
|
||||
* подождать некоторое время, в расчете что проблемная операция
|
||||
чтения будет штатно завершена;
|
||||
|
||||
Однако, при аварийном отключении питания или сбое в ядре ОС, на диске будет
|
||||
сохранена только часть измененных страниц БД. При этом с большой вероятностью
|
||||
может оказаться так, что будут сохранены мета-страницы со ссылками на страницы
|
||||
с новыми версиями данных, но не сами новые данные. В этом случае БД будет
|
||||
безвозвратна разрушена, даже если до аварии производилась полная синхронизация
|
||||
данных (посредством `mdb_env_sync()`).
|
||||
* перервать текущую операцию изменения данных с возвратом кода
|
||||
ошибки.
|
||||
|
||||
В MDBX эта проблема решена путем полной переработки пути записи данных:
|
||||
3. Гарантия сохранности БД в режиме `WRITEMAP+MAPSYNC`.
|
||||
|
||||
* В режиме `WRITEMAP` MDBX не обновляет мета-страницы непосредственно,
|
||||
а поддерживает их теневые копии с переносом изменений после фиксации
|
||||
данных.
|
||||
При работе в режиме `WRITEMAP+MAPSYNC` запись измененных
|
||||
страниц выполняется ядром ОС, что имеет ряд преимуществ. Так
|
||||
например, при крахе приложения, ядро ОС сохранит все изменения.
|
||||
|
||||
* При завершении транзакций, в зависимости от состояния
|
||||
синхронности данных между диском и оперативной память, MDBX помечает
|
||||
точки фиксации либо как сильные (strong), либо как слабые (weak). Так
|
||||
например, в режиме `WRITEMAP` завершаемые транзакции помечаются как
|
||||
слабые, а при явной синхронизации данных как сильные.
|
||||
Однако, при аварийном отключении питания или сбое в ядре ОС, на
|
||||
диске будет сохранена только часть измененных страниц БД. При
|
||||
этом с большой вероятностью может оказаться так, что будут
|
||||
сохранены мета-страницы со ссылками на страницы с новыми
|
||||
версиями данных, но не сами новые данные. В этом случае БД
|
||||
будет безвозвратна разрушена, даже если до аварии производилась
|
||||
полная синхронизация данных (посредством `mdb_env_sync()`).
|
||||
|
||||
* При открытии БД
|
||||
выполняется автоматический откат к последней сильной фиксации. Этим
|
||||
обеспечивается гарантия сохранности БД.
|
||||
В _libmdbx_ эта проблема устранена путем полной переработки
|
||||
пути записи данных:
|
||||
|
||||
К сожалению, такая гарантия надежности не дается бесплатно. Для сохранности
|
||||
данных, страницы формирующие крайний снимок с сильной фиксацией, не должны
|
||||
повторно использоваться (перезаписываться) до формирования следующей сильной
|
||||
точки фиксации. Таким образом, крайняя точки фиксации создает описанный выше
|
||||
эффект "долгого чтения", с разницей в том, что при исчерпании свободных
|
||||
страниц автоматически будет сформирована новая точка сильной фиксации.
|
||||
* В режиме `WRITEMAP+MAPSYNC` _libmdbx_ не обновляет
|
||||
мета-страницы непосредственно, а поддерживает их теневые копии
|
||||
с переносом изменений после фиксации данных.
|
||||
|
||||
В последующих версиях MDBX будут предусмотрены средства для асинхронной записи
|
||||
данных на диск с формированием сильных точек фиксации.
|
||||
* При завершении транзакций, в зависимости от состояния
|
||||
синхронности данных между диском и оперативной память,
|
||||
_libmdbx_ помечает точки фиксации либо как сильные (strong),
|
||||
либо как слабые (weak). Так например, в режиме
|
||||
`WRITEMAP+MAPSYNC` завершаемые транзакции помечаются как
|
||||
слабые, а при явной синхронизации данных как сильные.
|
||||
|
||||
4. Возможность автоматического формирования контрольных точек (сброса данных
|
||||
на диск) при накоплении заданного объёма изменений, устанавливаемого функцией
|
||||
* При открытии БД выполняется автоматический откат к последней
|
||||
сильной фиксации. Этим обеспечивается гарантия сохранности БД.
|
||||
|
||||
К сожалению, такая гарантия надежности не дается бесплатно. Для
|
||||
сохранности данных, страницы формирующие крайний снимок с
|
||||
сильной фиксацией, не должны повторно использоваться
|
||||
(перезаписываться) до формирования следующей сильной точки
|
||||
фиксации. Таким образом, крайняя точка фиксации создает
|
||||
описанный выше эффект "долгого чтения". Разница же здесь в том,
|
||||
что при исчерпании свободных страниц ситуация будет
|
||||
автоматически исправлена, посредством записи изменений на диск
|
||||
и формированием новой сильной точки фиксации.
|
||||
|
||||
В последующих версиях _libmdbx_ будут предусмотрены средства
|
||||
для асинхронной записи данных на диск с автоматическим
|
||||
формированием сильных точек фиксации.
|
||||
|
||||
4. Возможность автоматического формирования контрольных точек
|
||||
(сброса данных на диск) при накоплении заданного объёма
|
||||
изменений, устанавливаемого функцией
|
||||
`mdbx_env_set_syncbytes()`.
|
||||
|
||||
5. Возможность получить отставание текущей транзакции чтения от последней
|
||||
версии данных в БД посредством `mdbx_txn_straggler()`.
|
||||
5. Возможность получить отставание текущей транзакции чтения от
|
||||
последней версии данных в БД посредством
|
||||
`mdbx_txn_straggler()`.
|
||||
|
||||
6. Утилита mdbx_chk для проверки БД и функция `mdbx_env_pgwalk()` для обхода
|
||||
всех страниц БД.
|
||||
6. Утилита mdbx_chk для проверки БД и функция
|
||||
`mdbx_env_pgwalk()` для обхода всех страниц БД.
|
||||
|
||||
7. Управление отладкой и получение отладочных сообщений посредством
|
||||
`mdbx_setup_debug()`.
|
||||
7. Управление отладкой и получение отладочных сообщений
|
||||
посредством `mdbx_setup_debug()`.
|
||||
|
||||
8. Возможность связать с каждой завершаемой транзакцией до 3 дополнительных
|
||||
маркеров посредством `mdbx_canary_put()`, и прочитать их в транзакции чтения
|
||||
посредством `mdbx_canary_get()`.
|
||||
8. Возможность связать с каждой завершаемой транзакцией до 3
|
||||
дополнительных маркеров посредством `mdbx_canary_put()`, и
|
||||
прочитать их в транзакции чтения посредством
|
||||
`mdbx_canary_get()`.
|
||||
|
||||
9. Возможность узнать есть ли за текущей позицией курсора строка данных
|
||||
посредством `mdbx_cursor_eof()`.
|
||||
9. Возможность узнать есть ли за текущей позицией курсора
|
||||
строка данных посредством `mdbx_cursor_eof()`.
|
||||
|
||||
10. Возможность явно запросить обновление существующей записи, без создания
|
||||
новой посредством флажка `MDB_CURRENT` для `mdb_put()`.
|
||||
10. Возможность явно запросить обновление существующей записи,
|
||||
без создания новой посредством флажка `MDB_CURRENT` для
|
||||
`mdb_put()`.
|
||||
|
||||
11. Возможность обновить или удалить запись с получением предыдущего значения
|
||||
данных посредством `mdbx_replace()`.
|
||||
11. Возможность обновить или удалить запись с получением
|
||||
предыдущего значения данных посредством `mdbx_replace()`.
|
||||
|
||||
12. Поддержка ключей нулевого размера.
|
||||
|
||||
13. Исправленный вариант `mdb_cursor_count()`, возвращающий корректное
|
||||
количество дубликатов для всех типов таблиц и любого положения курсора.
|
||||
13. Исправленный вариант `mdb_cursor_count()`, возвращающий
|
||||
корректное количество дубликатов для всех типов таблиц и любого
|
||||
положения курсора.
|
||||
|
||||
14. Возможность открыть БД в эксклюзивном режиме посредством
|
||||
`mdbx_env_open_ex()`, например в целях её проверки.
|
||||
|
||||
15. Возможность закрыть БД в "грязном" состоянии (без сброса данных и
|
||||
формирования сильной точки фиксации) посредством `mdbx_env_close_ex()`.
|
||||
15. Возможность закрыть БД в "грязном" состоянии (без сброса
|
||||
данных и формирования сильной точки фиксации) посредством
|
||||
`mdbx_env_close_ex()`.
|
||||
|
||||
16. Возможность получить посредством `mdbx_env_info()` дополнительную
|
||||
информацию, включая номер самой старой версии БД (снимка данных), который
|
||||
используется одним из читателей.
|
||||
16. Возможность получить посредством `mdbx_env_info()`
|
||||
дополнительную информацию, включая номер самой старой версии БД
|
||||
(снимка данных), который используется одним из читателей.
|
||||
|
Loading…
x
Reference in New Issue
Block a user