We have a process that needs to analyze the contents of a whole LMDB. So far the approach was to open a read-only transaction and use a cursor to iterate over the whole contents in order. This long transaction apparently causes other concurrent process(es) to get MDB_MAP_FULL from mdb_put() even though that LMDB has plenty free pages at that moment. [...]It's a documented feature.
I haven't seen that in docs http://www.lmdb.tech/doc/
(I even skimmed the "internals" section) Am I missing some part?
It's just stated that _put functions can fail with MDB_MAP_FULL if
"the database is full" (and I wouldn't consider it "full" in my
case).
If that long transaction was getting MDB_TXN_FULL (or another
special error), that would be more understandable to me, but those
transactions appear OK and other short ones are getting
MDB_MAP_FULL. Right now I have no indication *when* to break
those read-only transactions, except for guessing based on
experiments.
if you can measure the "fullness" of LMDB while you read, you could suspend/resume the reading in the way I described at the beginning before LMDB gets too full.
I have no idea how to measure *this* kind of fullness. Our estimate shows there should be many free pages (even half of all)
MDB_stat st; // and use mdb_stat() size_t pgs_used = st.ms_branch_pages + st.ms_leaf_pages + st.ms_overflow_pages;
and this estimate won't change at all when done during the
read-only transaction. So the only thing to do that I can see is
at the RW transaction living in a different process: if a write
gives me MDB_MAP_FULL and the fullness estimate shows that a large
fraction of pages should be free, I might assume that the error
will just disappear soon (when the other process finishes its RO
transaction). That's not nice at all.
--Vladimir