#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.
#5137 fixed this for shinzo.
corekv takes a range iterator whenever
Prefixis nil and leaves badger's ownPrefixempty, so badger'sValid()is still true on the first key past the end. corekv then checks the bound in Go by callingItem()on that key, which registers it as a read. That key belongs to the next document, because datastore keys are ordered by a sequentialDocShortID.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
@indexanywhere. One transaction reads document 0 and writes document 0. A second transaction writes only document 1 and commits first.With the
GetDocumentcall txnA aborts. Without it, txnA commits. Changing that one field toPrefix: prefixmakes it commit as well, and all 30./internal/...packages pass with the change.Run on 2531f86, badger backend only.
corekv/memoryconflicts on its own operations rather than on a read set.