From 18f8836fdb2dd3d7ae81fa992aaaf5425b754db2 Mon Sep 17 00:00:00 2001 From: Nathan VanBenschoten Date: Thu, 30 Apr 2020 14:25:44 -0400 Subject: [PATCH] kv: declare write access to AbortSpan on all aborting EndTxn reqs Fixes #43707. Fixes #48046. Fixes #48189. Part of the change made by #42765 was to clear AbortSpan entries on non-poisoning, aborting EndTxn requests. Specifically, this change was made in 1328787. The change forgot to update the corresponding span declaration logic to reflect the fact that we were now writing to the AbortSpan in cases where we previously weren't. This was triggering an assertion in race builds that tried to catch this kind of undeclared span access. The assertion failure was very rare because it required the following conditions to all be met: 1. running a test with the race detector enabled 2. a txn (A) must have been aborted by another txn (B) 3. txn B must have cleared an intent on txn A's transaction record range 4. txn A must have noticed and issued a non-poisoning EndTxn(ABORT) We should backport this when we get a change (once v20.1.0 has stabilized), but I don't expect that this could actually cause any issues. The AbortSpan update was strictly a matter of performance and we should never be racing with another request that is trying to read the same AbortSpan entry. --- pkg/kv/kvserver/batcheval/cmd_end_transaction.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pkg/kv/kvserver/batcheval/cmd_end_transaction.go b/pkg/kv/kvserver/batcheval/cmd_end_transaction.go index 77f06a125469..05ce64a1a20e 100644 --- a/pkg/kv/kvserver/batcheval/cmd_end_transaction.go +++ b/pkg/kv/kvserver/batcheval/cmd_end_transaction.go @@ -69,7 +69,12 @@ func declareKeysEndTxn( header.Txn.AssertInitialized(context.TODO()) minTxnTS = header.Txn.MinTimestamp abortSpanAccess := spanset.SpanReadOnly - if !et.Commit && et.Poison { + if !et.Commit { + // Rollback EndTxn requests may write to the abort span, either if + // their Poison flag is set, in which case they will add an abort + // span entry, or if their Poison flag is not set and an abort span + // entry already exists on this Range, in which case they will clear + // that entry. abortSpanAccess = spanset.SpanReadWrite } latchSpans.AddNonMVCC(abortSpanAccess, roachpb.Span{