Howard Chu writes: > [email protected] wrote: >> Changes from a failed liblmdb operation can be visible. Sometimes >> the resulting DB will also be inconsistent. The operation should >> invalidate the affected transaction/cursors or revert the change. > > The transaction should be invalidated. Nothing more can be done > once any error occurs in a transaction.
That would break back-mdb for MDB_NOTFOUND/MDB_KEYEXIST. And at least MDB_KEYEXIST can happen after touching pages, which affects the txn size even if the change "does nothing". I expected to generally invalidate except in necessary cases, and from then on make more cases "gentle" at our convenience without spending much time on it. >> put(MDB_MULTIPLE) can write some of the provided items and then >> fail, but be able to keep the txn usable. (...) > > No, "partial success" is not allowed. A transaction is atomic, all > or nothing. It would be atomic like a partial OS write(). It'd be up to the user what to do next. Not that I care myself if it is supported. >> A failed txn could still grow the txn size, unless MDB "un-touches" >> pages which memcmp says have not changed, rewinds me_pglast and >> me_pghead, etc. Which seems a lot of work, likely not worth the >> trouble. > > pghead/pglast should not persist into the environment until a successful > commit. Until then any error should just discard them. Sorry, I meant a failed _operation_ could grow them and thus affect the committed freelist size. >> I think cursors need a C_INVALID flag, so future ops cannot give a >> surprising success result instead of failing: get(MDB_NEXT/MDB_PREV) >> take ~C_INITIALIZED to mean (re)start from the beginning/end. > > Good idea. ...or C_VALID so a single OR/AND can set/clear them both. >> Don't know how often reverting is a relevant option. (...) > > Reverting is irrelevant. Once a txn is aborted no changes are visible. True, but I meant while the txn is still live and usable. Hopefully it's only relevant for "nice to have" cases. -- Hallvard
