-
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
planner: check index valid while forUpdateRead #22152
Conversation
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
planner/core/logical_plan_builder.go
Outdated
if err != nil { | ||
return nil, err | ||
} | ||
} else { |
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 add this if else
~?
it seems buildTableRefsWithCache
will return tableDual when sel.From == nil
tidb/planner/core/logical_plan_builder.go
Line 309 in b45fa8b
p = b.buildTableDual() |
@@ -3599,7 +3608,7 @@ func (b *PlanBuilder) buildDataSource(ctx context.Context, tn *ast.TableName, as | |||
if tblName.L == "" { | |||
tblName = tn.Name | |||
} | |||
possiblePaths, err := getPossibleAccessPaths(b.ctx, b.TableHints(), tn.IndexHints, tbl, dbName, tblName) | |||
possiblePaths, err := getPossibleAccessPaths(b.ctx, b.TableHints(), tn.IndexHints, tbl, dbName, tblName, b.isForUpdateRead, b.is.SchemaMetaVersion()) |
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.
buildTableRefsWithCache
's cache mechanism should be taken care...(which buildDs during correlatedAggregateResolver#resolveSelect)
for sql:
create table t1(id int);
create table t2(id int);
select (select id from t2 limit 1 for update), id from t1;
the value in this line should be:
tbl | b.isForUpdateRead |
---|---|
t1 | false |
t2 | true |
but current get:
tbl | b.isForUpdateRead |
---|---|
t1 | false |
t2 | false |
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.
Good catch, added some cases for resolveSelect
.
LGTM |
I have a question about forUpdateRead. insert into t1(id, v, v2) select (select id from t where v = 33), v, v2 from t where v = 34;
select (select id from t where v = 33), v, v2 from t where v = 34 for update; For the above SQLs, |
Signed-off-by: you06 <you1474600@gmail.com>
Signed-off-by: you06 <you1474600@gmail.com>
Signed-off-by: you06 <you1474600@gmail.com>
Signed-off-by: you06 <you1474600@gmail.com>
for mysql,
|
@lysu For TiDB I remember the subquery always use snapshot read, it that right? |
it seems tidb work well for those test in decorrelated-subquery, but maybe it will break when correlate-subquery(for example: be rewriten into a join) 😂 lock-read in subquery is corner case...maybe we can check it later - -
|
That is a problem.. Actually if two statements are equal from the planner prospective but returns different results.. |
Seems here it's coupled with planner much more than we think for the |
Signed-off-by: you06 <you1474600@gmail.com>
945f4cf forbid the propagate of current read for correlate-aggregate query, in another word, correlate-subquery should use snapshot read unless it has forUpdate decorated, we got the following result then.
|
@you06 |
Signed-off-by: you06 <you1474600@gmail.com>
Yes, and I added the case, the capture mechanism should be patches to release-4.0 also. |
@lysu PTAL |
planner/core/expression_rewriter.go
Outdated
// capture the forUpdateRead mark | ||
isForUpdateRead := b.isForUpdateRead | ||
b.isForUpdateRead = false | ||
expr, resultPlan, err := b.rewriteWithPreprocess(ctx, exprNode, p, aggMapper, nil, asScalar, nil) | ||
b.isForUpdateRead = isForUpdateRead |
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 seems without this change, TestIssue21498 still can work
and it seems subQuery in Projection will call rewriteWithPreprocess
directly
tidb/planner/core/logical_plan_builder.go
Line 1222 in f6cac2f
newExpr, np, err := b.rewriteWithPreprocess(ctx, field.Expr, p, mapper, windowMapper, true, 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.
Yeah, removed the capture now, at least not in this PR.
@@ -2253,6 +2253,10 @@ func (r *correlatedAggregateResolver) resolveSelect(sel *ast.SelectStmt) (err er | |||
if err != nil { | |||
return err | |||
} | |||
// do not use cache when for update read | |||
if isForUpdateReadSelectLock(sel.LockInfo) { | |||
useCache = false |
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.
after debug, it seems useCache = false
only not-use-cache, but it still refill cache..
so in Access Path Selection will happen in correlatedAggregateResolver
and directly use cache in later buildProjection
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.
Seems useCache = false
only cache sub-sub-query when there is a select stmt inside from clause.
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 added some cases for sub queries, the cache problem is also related with rewrite, it may be solved together with it.
Signed-off-by: you06 <you1474600@gmail.com>
LGTM |
1 similar comment
LGTM |
/merge |
/run-all-tests |
Signed-off-by: ti-srebot <ti-srebot@pingcap.com>
cherry pick to release-5.0-rc in PR #22365 |
What problem does this PR solve?
cherry pick #21596 to master as a temporary solution.
Issue Number: close #21498
Problem Summary:
ForUpdateRead will read data using schema version of startTS, this may lead to incorrectness, the cases are listed in #21498
What is changed and how it works?
What's Changed:
For RC and forUpdateRead in RR, check if index's state is still
StatePublic
.How it Works:
This check confirms index between snapshotTS and forUpdateTS is not changed, otherwise, the index should not be used.
Related changes
pingcap/docs
/pingcap/docs-cn
:Check List
Tests
Side effects
Release note