Skip to content

Document fetcher reads the next document's key #5257

Description

@mennatnaga

#5137 fixed this for shinzo.

corekv takes a range iterator whenever Prefix is nil and leaves badger's own Prefix empty, so badger's Valid() is still true on the first key past the end. corekv then checks the bound in Go by calling Item() on that key, which registers it as a read. That key belongs to the next document, because datastore keys are ordered by a sequential DocShortID.

So a transaction that reads one document can be aborted by a concurrent write to a document it never touched. On a whole-collection scan the boundary key is in the next collection.

How to reproduce

Two documents, no @index anywhere. One transaction reads document 0 and writes document 0. A second transaction writes only document 1 and commits first.

// txnA
_, err = colA.GetDocument(ctxA, docs[0].ID())   // the only line that differs from the control
require.NoError(t, colA.UpdateDocument(ctxA, docs[0]))

// txnB writes docs[1] and commits, then:
err = txnA.Commit()   // corekv.ErrTxnConflict

With the GetDocument call txnA aborts. Without it, txnA commits. Changing that one field to Prefix: prefix makes it commit as well, and all 30 ./internal/... packages pass with the change.

Run on 2531f86, badger backend only. corekv/memory conflicts on its own operations rather than on a read set.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions