Howard Chu writes:
h.b.furuseth(a)usit.uio.no 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