-
Notifications
You must be signed in to change notification settings - Fork 5.8k
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
txn: support read consistency read with ts checking #32922
Conversation
[REVIEW NOTIFICATION] This pull request has been approved by:
To complete the pull request process, please ask the reviewers in the list to review by filling The full list of commands accepted by this bot can be found here. Reviewer can indicate their review by submitting an approval review. |
f9b9555
to
878eea0
Compare
878eea0
to
89e3275
Compare
@@ -1849,6 +1849,17 @@ func (cc *clientConn) handleQuery(ctx context.Context, sql string) (err error) { | |||
} | |||
retryable, err = cc.handleStmt(ctx, stmt, parserWarns, i == len(stmts)-1) | |||
if err != nil { | |||
if retryable && cc.ctx.GetSessionVars().IsRcCheckTsRetryable(err) { |
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.
If it's not retryable, will it raise an error to the client?
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.
Yes, the write conflict error
will be returned.
@@ -246,6 +246,8 @@ func (builder *RequestBuilder) SetFromSessionVars(sv *variable.SessionVars) *Req | |||
} | |||
if sv.StmtCtx.WeakConsistency { | |||
builder.Request.IsolationLevel = kv.RC | |||
} else if sv.StmtCtx.RCCheckTS { | |||
builder.Request.IsolationLevel = kv.RCCheckTS |
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.
So weak consistency will override it, though both of them are barely used...
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.
It's ok to override if the tikv-rc
is enabled as no transaction sematics is kept.
if rcReadTS == 0 { | ||
rcReadTS = b.ctx.GetSessionVars().TxnCtx.StartTS | ||
} | ||
return UpdateForUpdateTS(b.ctx, rcReadTS) |
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.
If rcReadTS != 0, do we need call UpdateForUpdateTS
? Can we optimize it to call UpdateForUpdateTS
only once here ?
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.
Only SELECT
statement call function refreshForUpdateTSForRC
?
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.
It's expected to update the for_update_ts
each time using the last valid read_ts
. refreshForUpdateTSForRC
will be used by write statements too in updateForUpdateTSIfNeeded
.
executor/executor.go
Outdated
@@ -1881,6 +1881,12 @@ func ResetContextOfStmt(ctx sessionctx.Context, s ast.StmtNode) (err error) { | |||
sc.NotFillCache = !opts.SQLCache | |||
} | |||
sc.WeakConsistency = isWeakConsistencyRead(ctx, stmt) | |||
// Try to mark the `RCCheckTS` flag for the first time execution of in-transaction read requests | |||
// using read-consistency isolation level. | |||
if ctx.GetSessionVars().ConnectionID > 0 && ctx.GetSessionVars().RcReadCheckTS && |
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.
Do we need add a transaction !AutoCommitTxn()
&& SelectCmd
here?
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.
Select
is already guaranteed in the above case
condition. !AutoCommitTxn()
is needed I'll add it.
@@ -156,6 +156,9 @@ func (e *PointGetExecutor) Open(context.Context) error { | |||
} else { | |||
e.snapshot = e.ctx.GetSnapshotWithTS(snapshotTS) | |||
} | |||
if e.ctx.GetSessionVars().StmtCtx.RCCheckTS { |
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.
Why only PointGet and BatachPointGet need to process for RCCheckTS
specially ?
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.
These cop executor builder will set the isolation flag but these two executors use txn snapshot
directly.
return false | ||
} | ||
// The `RCCheckTS` flag of `stmtCtx` is reset d | ||
return s.RcReadCheckTS && s.StmtCtx.RCCheckTS && errors.ErrorEqual(err, kv.ErrWriteConflict) |
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.
We reuse the error code kv.ErrWriteConflict, does it affect the write sqls behavior when write-conflict occur really.
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 error is newly introduced to the SELECT
statements I think it'll not affect the original write statment path.
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.
May WriteConflict error be met during pessimistic lock phase when executing a DML statement, and then checked by this function?
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've added another condition judgement checking if it's read only statement.
@@ -977,6 +977,10 @@ func (worker *copIteratorWorker) handleCopResponse(bo *Backoffer, rpcCtx *tikv.R | |||
zap.Uint64("regionID", task.region.GetID()), | |||
zap.String("storeAddr", task.storeAddr), | |||
zap.Error(err)) | |||
if strings.Contains(err.Error(), "write conflict") { |
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.
Do we need add a limitation that is a "Rc Check Ts read" ? I mean whether some other scenes make a "write conflict" here.
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.
In the read path only the added path may return other error
contains "write conflit", it's a bit difficult to visit stmtCtx
here. Also the returned error will be checked if the retry could be done in the upper layer so maybe it's enough.
item, err := r.txn.Get(key) | ||
if err != nil && err != badger.ErrKeyNotFound { | ||
return nil, errors.Trace(err) | ||
} | ||
if item == nil { | ||
return nil, nil | ||
} | ||
if r.RcCheckTS { |
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.
Do we have any test case for this process?
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.
The test in tidb_test.go would use mockstore and the path is covered there.
if !isWriteLock { | ||
return nil | ||
} | ||
return &kverrors.ErrConflict{ |
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.
Whatever lock.startTS>=startTS or lock.startTS < startTS, if lock was not resloved, returns ErrConflict
. Is it reasonable?
If lock was committed and lock.startTS<startTS, I think it should not return an error.
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.
The read ts in RcCheckTS
isolation level could be stale, so it could not be used to decide whether the lock could be skipped comparing ts.
89e3275
to
8d33247
Compare
/run-all-tests |
3aa2b4c
to
21bda04
Compare
21bda04
to
d7d0cb2
Compare
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.
rest LGTM
d7d0cb2
to
5763d32
Compare
Co-authored-by: Lei Zhao <[email protected]>
Co-authored-by: Lei Zhao <[email protected]>
Co-authored-by: Lei Zhao <[email protected]>
/merge |
/run-unit-test |
/merge |
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.
LGTM
/merge |
/run-unit-test |
/merge |
@cfzjywxk: Your PR was out of date, I have automatically updated it for you. At the same time I will also trigger all tests for you: /run-all-tests If the CI test fails, you just re-trigger the test that failed and the bot will merge the PR for you after the CI passes. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the ti-community-infra/tichi repository. |
/merge |
What problem does this PR solve?
Issue Number: close #33159
Problem Summary:
Try to support the read-consistency read with tso checking optimization.
What is changed and how it works?
for_update_ts
. If the read check has failed, the select statement will be retried only if no result chunk has been sent back to the mysql client yet , a new global ts will be fetched doing retry.tidb_rc_read_check_ts
is added to control whether the new path will be used, the default value is false.Check List
Tests
Side effects
Documentation
Release note