Sitelet https://github.com/erigontech/mdbx-go/releases
Skip to content

Releases: erigontech/mdbx-go

v0.44.0 — libmdbx v0.14.4

Choose a tag to compare

@AskAlexSharov AskAlexSharov released this 24 Sep 08:07
3310def

Vendored libmdbx moves from v0.14.3 (251562b2, 2026-08-09) to the v0.14.4 "Skynet Eve" (Накануне Skynet) release (2026-09-18), a bugfix release of the stable branch. The public C API is unchanged — the mdbx.h diff is documentation only — so the bindings needed no adaptation. The Go side gains the copy/defrag API and one env option.

Go API additions

  • Env.Copy, Env.CopyFlag, Env.CopyFD, Env.CopyFDFlag are back (#223), rewired through the unified mdbx_env_copy / mdbx_env_copy2fd entry points. Copy/CopyFD do a plain as-is copy; CopyFlag/CopyFDFlag pass MDBX_CP_* through untouched — CopyDefaults, CopyCompact, CopyForceDynamicSize, CopyDontFlush, CopyThrottleMVCC, and CopyOverwrite for clobbering an existing target. CopyFDFlag casts the descriptor in C, so it compiles and is tested on Windows too.
  • Env.Defrag (#223), binding mdbx_env_defrag through a thin cgo helper, with DefragOptions (including TimeLimit, which travels as 1/65536-second units) and DefragResult. The environment must be opened Exclusive — cutting off trailing pages needs the whole-file lock; taking it per transaction is what trips ERROR_LOCK_VIOLATION on Windows. Documented on the method.
  • OptPresyncThreshold (#252), exposing MDBX_opt_presync_threshold.

Fixes

  • A cross-thread Txn.Abort panic no longer leaks closeLock (#254). Txn.abort unlocked manually at the end, and in strict thread mode strictThreadCheck panics by design when the aborting thread is not the one that began the txn — skipping that RUnlock and leaving the read lock held forever, so any later Env.Close blocked indefinitely. The panic is recoverable, so a caller could survive it and then deadlock on an unrelated Close. Draining a txn pool begun on other goroutines is exactly that case. Now released with defer, matching Txn.Park and Txn.Unpark.

libmdbx v0.14.4

  • Windows: stricter placement checks on network, shared and layered volumes, to prevent database corruption and data loss. Upstream lists this as a backward-compatibility break: a database on such a volume can now fail to open with MDBX_EREMOTE (ERROR_REMOTE_STORAGE_MEDIA_ERROR), notably with WOF active on compressed volumes.
  • Missing sub-page header check in page_check(), which could SIGSEGV while checking a corrupted database.
  • Regression returning MDBX_BAD_TXN instead of MDBX_OUSTED in particular cases.
  • Division truncation in default_rp_augment_limit(), which yielded a too low and "stepwise" default MDBX_opt_rp_augment_limit.
  • mdbx_get_sysraminfo() internals refined: sysinfo() plus MemAvailable on Linux, host_statistics64() on macOS.
  • Windows build fixes: CLANG/LLVM including Microsoft Clang, scan4seq_neon() for ARM64, Win32 with MDBX_NATIVE_SEH=OFF without MASM, _except_handler4 in 32-bit MDBX_WITHOUT_MSVC_CRT=ON builds.

One local fix on top of v0.14.4

v0.14.4's new macOS path passes HOST_VM_INFO_COUNT (15) to host_statistics64(HOST_VM_INFO64, ...), which wants HOST_VM_INFO64_COUNT (104) and returns KERN_FAILURE otherwise. On a straight v0.14.4, mdbx_get_sysraminfo() therefore fails with MDBX_ENOSYS on every macOS build, and libmdbx's own default_dp_limit() silently falls back to its worst-case estimate. mdbx-go carries the one-token fix, marked mdbx-go local fix in libmdbx/mdbx.c; it will be dropped once upstream takes it.

Build and tests

  • make cp re-vendors with git archive (#253) instead of copying the working tree: only files tracked at the requested ref are vendored, build artifacts left in the clone stay out, and files deleted upstream are dropped instead of lingering. make cp LIBMDBX_REF=v0.14.4.
  • Rebuilding after a re-vendor needs go build -a (#259, now in the README). The mdbx package pulls libmdbx/mdbx.c in through a cgo #include across package directories, which the Go build cache does not track — a plain go test re-runs the old C. Verified: with the macOS fix above reverted, go test -count=1 ./mdbx still passed.
  • Tests that begin a write txn now lock the OS thread (#256, #223). Without it the goroutine can migrate before the commit or abort, libmdbx returns MDBX_THREAD_MISMATCH, the write txn stays alive and mdbx_env_close returns MDBX_BUSY — invisible off Windows until setup's cleanup started reporting the Close error.

v0.43.0 — libmdbx v0.14.3

Choose a tag to compare

@AskAlexSharov AskAlexSharov released this 16 Aug 05:03
f8b27ce

Vendored libmdbx moves from v0.14.2 (530d0265, 2026-05-14) to the v0.14.3 "Китов" (Kitov) release (2026-08-09). No Go API changes — the only source edits are one constant remapping and Godoc.

Data-loss and hang fixes

  • Copy without compaction produced a copy without payload. In v0.14.2 a non-compacting mdbx_env_copy built the destination meta-pages from the empty model — the source tree roots and geometry were never carried over — so the copy opened cleanly and read as an empty database. Verified fixed here: a fill/copy/re-read probe over MDBX_CP_DEFAULTS and MDBX_CP_FORCE_DYNAMIC_SIZE round-trips the full payload, where the same probe read an empty database against v0.14.2.
  • Lost table content after aborting a nested transaction that dropped the table.
  • Infinite loop in mdbx_txn_abort() from a memcmp()/memcpy() typo.
  • env_owned_wrtxn() bypassed locking under MDBX_NOSTICKYTHREADS — the mode mdbx-go always sets.
  • Major typo in latch_maindb_locked(); missing return on an error path in mdbx_cursor_bind().

Spilling and cursors

Fixes concentrated in large write transactions: committing a pure nested transaction that has spilled pages; leak of the spilled-pages list on nested-transaction abort; tracking and invalidation of the inner part of sibling cursors; the cursor stack reworked around a page stash; spilling and accounting corrected for MDBX_AVOID_MSYNC=ON.

Leaks

mach_port_t in mdbx_get_sysraminfo(), Windows section handle in osal_mresize(), table name in dbi_open_locked(), cond_pair in copy_with_compacting().

Windows

ERROR_LOCK_VIOLATION during defrag in overlapped-I/O modes; lost global init and TLS destructors in MinGW static builds; /experimental:c11atomics workaround plus a compile-time guard against wrong MSVC codegen for C11 atomics on non-x86.

Go side

  • NoTLS now maps to MDBX_NOSTICKYTHREADS. libmdbx removed the deprecated MDBX_NOTLS alias, superseded by MDBX_NOSTICKYTHREADS since 0.13. The constant stays Deprecated, keeps the same value and keeps existing callers compiling — prefer NoStickyThreads.
  • Env.Open now documents a deadlock risk. As of libmdbx 0.14.x the env functions that need the writer lock but take no txn — SetFlags, SetOption, SetGeometry, Sync/SyncForce/SyncPoll, Stat/Info(nil), Close — acquire that lock when the calling goroutine does not own the in-flight write transaction. mdbx-go always sets NoStickyThreads, so calling one of them from a goroutine the writer is waiting on can deadlock. Make such calls from the writer's own goroutine, or while no write transaction is running.
  • Env.Sync Godoc no longer names MapAsync, an upstream-removed alias mdbx-go never exposed.

mdbx_replace_ex() changed upstream to return only previous data, never new — mdbx-go does not bind it.

Full changelog: v0.42.0...v0.43.0

v0.42.0

Choose a tag to compare

@AskAlexSharov AskAlexSharov released this 05 Aug 06:54
155c45c

Go-side release. Vendored libmdbx is unchanged from v0.41.x — still v0.14.2 (530d0265).

Backward compatibility breaks

  • Txn.Unpark gains a result value (#236): Unpark() error → Unpark() (restarted bool, err error). Single-value assignments need _, err =. MDBX_RESULT_TRUE from mdbx_txn_unpark — ousted and restarted on a newer snapshot — was previously collapsed into plain success while the cached Txn.ID() kept the pre-restart value.
  • Cursor and Txn can no longer be copied (#250): both carry a noCopy marker, so go vet copylocks flags any copy. Copying either was always a bug — the copy would share the same C handle and double-close it. Embedding as a struct field is not a copy and stays fine.

New

  • Cursor.Open(txn, db) (#248) initializes an unopened Cursor in place, so callers may embed Cursor by value instead of holding a *Cursor. Txn.OpenCursor keeps its signature and delegates. Cursor.IsClosed() exposes the closed state that callers previously read off a nil *Cursor; it is nil-safe.

Fixes

  • Unpark reported errors under the op name mdbx_txn_park (#236).
  • Park/Unpark checked env._env without the close guard that abort() takes, racing Env.Close (#236).

CI

  • golangci-lint config simplified, nilness bug-catcher added, workflows hardened (#244).

v0.41.2

Choose a tag to compare

@AskAlexSharov AskAlexSharov released this 05 Aug 07:00
3d99453

Patch release on top of v0.41.1. Compile-time only — no runtime behaviour change.

noCopy on the C-handle types

v0.41.1 added Cursor.Open so a Cursor can be embedded by value, which also makes copying one easy to do by accident. A Cursor or Txn owns a raw libmdbx handle, so a copy hands two Go values one handle: closing either frees it while the other still points at it, and the second close is a double free into cgo.

type before now
Env already rejected — holds sync.RWMutex unchanged
Txn unguarded noCopy
Cursor unguarded noCopy

go vet -copylocks now rejects the copy:

assignment copies lock value to b: mdbx.Cursor contains mdbx.noCopy

Embedding by value — the reason Open exists — is unaffected; noCopy bars copying a value, not holding one. sizeof(Cursor) is unchanged at 16 bytes.

Full changelog: v0.41.1...v0.41.2

v0.41.1

Choose a tag to compare

@AskAlexSharov AskAlexSharov released this 05 Aug 05:33
afa609b

Patch release on top of v0.41.0. One change, backported from #248 via #249.

Cursor.Open — in-place initialization

Txn.OpenCursor always heap-allocates a *Cursor. Cursor.Open initializes an existing Cursor in place, so callers can embed one by value and drop a per-cursor allocation:

type MyCursor struct {
    c mdbx.Cursor   // by value, no separate allocation
}

if err := m.c.Open(txn, dbi); err != nil { ... }
defer m.c.Close()

Close is still required, and Txn.OpenCursor is unchanged for existing callers.

IsClosed() reports the state callers previously read off a nil *Cursor.

Nil handling

IsClosed and Close are nil-safe, so var c *Cursor; c.IsClosed() reports closed instead of panicking — that is what lets IsClosed actually replace the old nil checks.

Open returns descriptive errors rather than dereferencing:

  • nil receiver — there is nothing to initialize in place
  • nil transaction — easy to hit when a caller has not begun its txn, and a cgo nil dereference says nothing useful

Not changed: Renew, Bind and Unbind dereference the same way. Pre-existing, and left for a follow-up.

Full changelog: v0.41.0...v0.41.1

v0.41.0

Choose a tag to compare

@AskAlexSharov AskAlexSharov released this 23 Jul 08:37
03f9f60

Headline: the cursor-leak fix (#229) plus a batch of correctness, API, and tooling improvements accumulated since v0.40.3.

⚠️ Requirements

  • Go 1.25+ is now required (#243).

Bug fixes

  • Cursor leak: Cursor.Close() no longer skips mdbx_cursor_close after a write txn ends — that leaked the C cursor allocation. Also hardens cursor lifecycle (nil/unbound guards, CursorToPool unbind) (#229). (Backported to v0.40.3.1 and v0.39.19.1.)
  • Env.Close now surfaces the mdbx_env_close error instead of leaking the handle on failure (#230).
  • Txn.Reset now returns the mdbx_txn_reset error (#235).

API / behavior

  • Env.Close and Txn.Reset gain an error return — source-compatible for statement/defer call sites; *Env now satisfies io.Closer (#230, #235).
  • Added OptDpReserveLimit; deprecated the misnamed OptDpReverseLimit alias (#234).
  • Env.Info(nil) passes a NULL txn instead of opening a throwaway read transaction — fewer cgo calls, no reader-slot churn (#231).

Performance

  • Cursor.Get builds result slices directly from the C result, dropping the per-Txn scratch round-trip (#237).

Docs

  • Corrected the zero-copy read semantics (no RawRead) and removed stale finalizer claims (#233, #232).

Tooling / internal

  • CI: erigon make test-short integration job (#241); golangci-lint v2.12.2 with an expanded, curated linter set (#242, #243).
  • Removed dead callback machinery and stale comments (#239).

Full diff: v0.40.3...v0.41.0

v0.40.3.1 — cursor leak fix (backport)

Choose a tag to compare

@AskAlexSharov AskAlexSharov released this 23 Jul 08:37
014127a

Patch release on the v0.40.3 line backporting the cursor-leak fix (#246).

Cursor.Close() skipped mdbx_cursor_close when the write transaction had already terminated, on the LMDB-era assumption that libmdbx frees the cursor at txn end. It does not — txn end only marks cursors reusable; mdbx_cursor_close frees them. So every cursor closed after its write txn ended leaked its C-side allocation (an unbounded C-heap leak under cursor-heavy write workloads). Close() now always frees the cursor.

Minimal, low-risk backport (only the Close() change). Consumers pinned to v0.40.3 should upgrade to v0.40.3.1.

v0.39.19.1 — cursor leak fix (backport)

Choose a tag to compare

@AskAlexSharov AskAlexSharov released this 23 Jul 08:37
77f2347

Patch release on the v0.39.19 line backporting the cursor-leak fix (#247).

Cursor.Close() skipped mdbx_cursor_close when the write transaction had already terminated, on the LMDB-era assumption that libmdbx frees the cursor at txn end. It does not — so every cursor closed after its write txn ended leaked its C-side allocation. Close() now always frees the cursor.

Minimal, low-risk backport (only the Close() change). Consumers pinned to v0.39.x should upgrade to v0.39.19.1.

v0.40.3

Choose a tag to compare

@AskAlexSharov AskAlexSharov released this 08 Jul 08:00
59795c0

What's Changed

Full Changelog: v0.40.2...v0.40.3

v0.40.2 range estimation/delete/distribution APIs

Choose a tag to compare

@AskAlexSharov AskAlexSharov released this 19 Jun 09:57
b63d3e3

What's Changed

  • Readers metrics and last master of libmdbx by @JkLondon in #216
  • mdbx: expose ExactKeyValue/Pair navigation flags + merge last master by @JkLondon in #217
  • new 0.14.2 mdbx release by @JkLondon in #218
  • upgrade cgosymbolizer to latest by @AskAlexSharov in #219
  • mdbx: replace interface{} with any (Go 1.18 alias) by @AskAlexSharov in #220
  • Refresh README: erigontech path, libmdbx version badge, quickstart, sourcecraft links by @JkLondon in #222
  • mdbx: expose Refresh / Checkpoint / CommitEmbarkRead / Rollback / Amend / Clone txn APIs by @JkLondon in #221
  • mdbx: expose OptPrefaultWriteEnable by @AskAlexSharov in #224
  • mdbx: expose range estimation + cursor distribution/deletion APIs by @AskAlexSharov in #225

Full Changelog: v0.39.18...v0.40.2