-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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
Introduce a BeginTransaction request. #2799
Conversation
This PR isn't finished yet...there are two failing unittests (and looks like there are merge conflicts...again). @bdarnell : the TestStoreRangeDownReplicate test is broken in @petermattis , @vivekmenezes : the sql LogicTest is failing with this |
eb64586
to
50d25e1
Compare
The SQL logic test failures that I looked at were all the same root problem. We were modifying the schema (e.g. adding a unique index) and found an error that was unrelated to the conditional puts we performed. For example,
That's a conditional put failure, but as I said we wrote to the key using |
@petermattis Ah, good call. IIRC, @tschottdorf introduced an index into the error for batches. That would get screwed up because we insert the begin transaction request and then remove it. I'll look into fixing that. The other problem with raft remains however. |
// the first transactional write. Also enforce that no transactional | ||
// writes occur before a begin transaction. | ||
var haveBeginTxn bool | ||
for _, req := range ba.Requests { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
take a look at ba.GetArg(proto.BeginTransactionRequest)
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I need to go through them all in order to check for error conditions.
Is the client code really the right place to insert this call? It seems like we're shoving more complexity into the client though we could do that in the coordinator transparently. I assumed that's what you were doing before I saw the client changes (it's not like you didn't explain it, but alas), so some of my comments will refer to this erroneously. |
Yes, that'll be it. Just go for a hotfix for now; I'm filing an issue. We should move the error index out of the error. |
I can't reproduce this - do you have a log? I can, however, reproduce a timing-dependent failure in the down-replicate phase of this test. The transaction record is created successfully, but it's not there by the time EndTransaction is called. This looks like a race between the RangeGCQueue and the operations on this range. This test is artificially accelerating the clock to expire leases and running GC scans, which are the normal means by which we avoid this race in the real world (although we should probably also have something more iron-clad). |
@tschottdorf I'm going to leave this stuff in the client. There's parity there with the end transaction stuff and I'm by no means convinced that the coordinator will always have enough information (with future directions) to determine the beginning of a txn. |
432c77b
to
ca6ef78
Compare
BeginTransactionRequest is automatically inserted by the KV client immediately before the first transactional write. On execution, BeginTransaction creates the transaction record. If a heartbeat arrives for a txn that has no transaction record, it's ignored. If a push txn arrives for a txn that has no transaction record, the txn is considered aborted. This solves the problem of errant heartbeats or pushes recreating a GC'd transaction record, addressing #2062.
ca6ef78
to
ca96b85
Compare
Introduce a BeginTransaction request.
if !haveTxnWrite { | ||
haveTxnWrite = roachpb.IsTransactionWrite(args) | ||
if roachpb.IsTransactionWrite(args) && firstWriteIndex == -1 { | ||
firstWriteKey = args.Header().Key |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
doesn't this end up being the last write key?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
err, disregard
I understand that you wanted to get this out of your queue, but please leave future PRs open for discussion at least up to the first LGTM. |
br.Responses = append(br.Responses[:firstWriteIndex], br.Responses[firstWriteIndex+1:]...) | ||
} | ||
// Handle case where inserted begin txn confused an indexed error. | ||
if pErr != nil && pErr.Detail != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is just if iErr, ok := pErr.GoError().(roachpb.IndexedError) {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK.
My mistake. Thought this was already LGTM. |
@tschottdorf Will send another PR with fixes. |
fixes cockroachdb#2717 (ok since cockroachdb#2799 has landed).
BeginTransactionRequest is automatically inserted by the KV client
immediately before the first transactional write. On execution,
BeginTransaction creates the transaction record.
If a heartbeat arrives for a txn that has no transaction record, it's
ignored. If a push txn arrives for a txn that has no transaction record,
the txn is considered aborted.
This solves the problem of errant heartbeats or pushes recreating a GC'd
transaction record, addressing #2062.