Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

kv: non-transactional batches can be split into sub-batches #46081

Open
danhhz opened this issue Mar 13, 2020 · 2 comments
Open

kv: non-transactional batches can be split into sub-batches #46081

danhhz opened this issue Mar 13, 2020 · 2 comments
Assignees
Labels
A-kv Anything in KV that doesn't belong in a more specific category. T-kv KV Team
Projects

Comments

@danhhz
Copy link
Contributor

danhhz commented Mar 13, 2020

Discussed in #46017 (review)

The following diff on top of #46017 finds a kv.Batch committed via kv.DB that has writes with two different timestamps.

diff --git a/pkg/kv/kvnemesis/generator.go b/pkg/kv/kvnemesis/generator.go
index 6cf485c0b7..b438be4a40 100644
--- a/pkg/kv/kvnemesis/generator.go
+++ b/pkg/kv/kvnemesis/generator.go
@@ -179,7 +179,7 @@ func NewDefaultConfig() GeneratorConfig {
 	// nontransactional batch are disjoint and upgrading to a transactional batch
 	// (see CrossRangeTxnWrapperSender) if they are. roachpb.SpanGroup can be used
 	// to efficiently check this.
-	config.Ops.Batch = BatchOperationConfig{}
+	config.Ops.Batch.Ops.PutExisting = 0
 	return config
 }
  {
    b := &Batch{}
    b.Put(ctx, /Table/50/"c1556caf", v-5) // nil
    b.Get(ctx, /Table/50/"43275686") // (nil, nil)
    b.Put(ctx, /Table/50/"0998fa3b", v-6) // nil
    db0.Run(ctx, b) // nil
  }
committed batch different timestamps: /Table/50/"0998fa3b":1583976139.381769000,0->v-6 /Table/50/"c1556caf":1583976139.381491000,0->v-5

Diagnosis by @nvanbenschoten

we're just straight-up missing a check that non-transactional batches don't get split into sub-batches due to request compatibility rules (as opposed to range boundaries). We'd want something like:

diff --git a/pkg/kv/kvclient/kvcoord/dist_sender.go b/pkg/kv/kvclient/kvcoord/dist_sender.go
index 36954d9867..9ff2620ddd 100644
--- a/pkg/kv/kvclient/kvcoord/dist_sender.go
+++ b/pkg/kv/kvclient/kvcoord/dist_sender.go
@@ -692,6 +693,12 @@ func (ds *DistSender) Send(
                splitET = true
        }
        parts := splitBatchAndCheckForRefreshSpans(ba, splitET)
+       if len(parts) > 1 && ba.Txn == nil && ba.IsTransactional() && ba.ReadConsistency == roachpb.CONSISTENT {
+               // If there's no transaction and ba spans ranges, possibly re-run as part of
+               // a transaction for consistency. The case where we don't need to re-run is
+               // if the read consistency is not required.
+               return nil, roachpb.NewError(&roachpb.OpRequiresTxnError{})
+       }
        if len(parts) > 1 && (ba.MaxSpanRequestKeys != 0 || ba.TargetBytes != 0) {
                // We already verified above that the batch contains only scan requests of the same type.
                // Such a batch should never need splitting.

Found by kvnemesis.

Jira issue: CRDB-5106

@danhhz danhhz added the A-kv Anything in KV that doesn't belong in a more specific category. label Mar 13, 2020
@danhhz danhhz added this to Incoming in KV via automation Mar 13, 2020
@lunevalex lunevalex moved this from Incoming to Transactions in KV Jul 29, 2020
@nvanbenschoten nvanbenschoten changed the title kv: inconsistent batch timestamps kv: non-transactional batches can be split into sub-batches Aug 12, 2020
@lunevalex lunevalex moved this from Transactions to Cold storage in KV Apr 23, 2021
@jlinder jlinder added the T-kv KV Team label Jun 16, 2021
tbg added a commit to tbg/cockroach that referenced this issue Sep 20, 2022
This shouldn't have an effect because we still zero out
`config.Ops.Batch` owing to cockroachdb#46081.

See also cockroachdb#71236.

Release note: None
@tbg
Copy link
Member

tbg commented Oct 24, 2022

The snippet above has made it into DistSender,

// If there's no transaction and ba spans ranges, possibly re-run as part of
// a transaction for consistency. The case where we don't need to re-run is
// if the read consistency is not required.
if ba.Txn == nil && ba.IsTransactional() && ba.ReadConsistency == roachpb.CONSISTENT {
return nil, roachpb.NewError(&roachpb.OpRequiresTxnError{})
}

but I just ran into the issue again. The problem is that once we add DeleteRangeUsingTombstone1, a batch containing that request will happily be split into two parts, so kvnemesis potentially sees multiple mvcc timestamps for it.

Just pointing this out; this can't really be fixed. But the snippet above is problematic if we were to start mixing DeleteRangeUsingTombstone with, say, a Put. That would result in a batch that claims to be "transactional" and we'd restart in a txn and then fail, since mvcc range deletions are unsupported in the context of a transaction.

So the check is wrong in that sense. ba.IsTransactional() means "contains a request that can be used in a txn". What we need is that all requests can be used in a txn.

Besides this also seems to be a real footgun in the KV API. I think we tend to always assume that batches are atomic, but here it's very clear that they mostly, but not always, are. This subtlety is confusing; ideally batches would opt into being split explicitly, and we would always return an error for batches that don't opt in but could in theory require splitting.

We have an isUnsplittable flag - only used for AddSSTable - which isn't really a great solution in general, since it is a property of the request type, where really it is something different callers may think differently about, or in the worst case not think about at all.

Footnotes

  1. https://github.com/cockroachdb/cockroach/issues/76435

Copy link

We have marked this issue as stale because it has been inactive for
18 months. If this issue is still relevant, removing the stale label
or adding a comment will keep it active. Otherwise, we'll close it in
10 days to keep the issue queue tidy. Thank you for your contribution
to CockroachDB!

@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Apr 29, 2024
@yuzefovich yuzefovich reopened this May 1, 2024
KV automation moved this from On Hold to Incoming May 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-kv Anything in KV that doesn't belong in a more specific category. T-kv KV Team
Projects
KV
Incoming
Development

No branches or pull requests

5 participants