mdbx: устранение yнаследованной от LMDB ошибки приводящей к повреждению БД при использовании MDBX_DUPFIXED (backport).

Тезисно:

 - Использование DUPFIXED (включая INTEGERDUP) могло приводить к
   повреждению БД и/или потере данных. Этот коммит устраняет эту угрозу.

 - Вероятность проявления существенно увеличивается с увеличением
   размера/длины мульти-значений/дубликатов (не ключей).

 - В MDBX проблема унаследована от LMDB, где существует более 11 лет,
   начиная с коммита ccc4d23e74
   и до настоящего времени.

Для вложенных страниц типа LEAF2 (которые содержат только значения
одинаковой длины, без таблицы смещений к ним), упомянутым выше коммитом,
было добавлено резервирование места (что в целом спорно, но в некоторых
сценариях позволяет уменьшить накладные расходы). Ошибка была в том, что
в коде не исключалась возможность превышения размера страницы БД, что
далее приводило к арифметическому переполнению, повреждению БД и/или
просписи памяти.
This commit is contained in:
Леонид Юрьев (Leonid Yuriev)
2024-02-28 16:11:09 +03:00
parent a0a4af7701
commit ea97fbae74
2 changed files with 135 additions and 18 deletions

View File

@@ -1376,8 +1376,12 @@ struct MDBX_env {
struct MDBX_lockinfo *me_lck;
unsigned me_psize; /* DB page size, initialized from me_os_psize */
unsigned me_leaf_nodemax; /* max size of a leaf-node */
unsigned me_branch_nodemax; /* max size of a branch-node */
uint16_t me_leaf_nodemax; /* max size of a leaf-node */
uint16_t me_branch_nodemax; /* max size of a branch-node */
uint16_t me_subpage_limit;
uint16_t me_subpage_room_threshold;
uint16_t me_subpage_reserve_prereq;
uint16_t me_subpage_reserve_limit;
atomic_pgno_t me_mlocked_pgno;
uint8_t me_psize2log; /* log2 of DB page size */
int8_t me_stuck_meta; /* recovery-only: target meta page or less that zero */