Okay, I think I see what's happening here:

mdb_find_oldest(): will return the most recent snapshot if no readers exist

mdb_page_alloc(): will search FREE_DBI for a transaction `last` that is
less than oldest, and will try to find a contiguous range of pages that
were free'd by said transaction, potentially merging free pages from many
transactions. If nothing is found, will instead grow the database.

Since `last` < `oldest` when we reuse any old pages, and we're only using
the 'freed' pages from last (not the data pages), we know that at the data
pages for the eldest two transactions are protected.

Is this right?

My earlier assumption (before reading mdb_page_alloc) was that LMDB would
be aggressive about grabbing pages freed by transactions that are not
actively being read. If we're relying on `last < oldest` to create a two
page discrepancy, this means when we actually have readers on older
transactions that we're being little more conservative than necessary. But
it does protect the last two snapshots.

...

Idle question: what happens with freeing old pages when the txnid_t wraps
around on a 32-bit system? Do the pages free'd by those transactions just
get stuck?

Reply via email to