-
Notifications
You must be signed in to change notification settings - Fork 5.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
executor: optimize delete your write #28806
Conversation
[REVIEW NOTIFICATION] This pull request has not been approved. 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. |
table/tables/tables.go
Outdated
@@ -802,6 +802,7 @@ func (t *TableCommon) AddRecord(sctx sessionctx.Context, r []types.Datum, opts . | |||
} | |||
} else { | |||
_, err = txn.Get(ctx, key) | |||
setPresume = true |
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 change is used to make the behaviour same for optimistic transactions regardless of the config tidb_constraint_check_in_place
. All the keys need existency check will go the Op_CheckNotExist
path in commit.
I tried this case and still can get a del record in write CF. /* s1 */ drop table if exists t;
/* s1 */ set session tidb_enable_clustered_index = 'off';
/* s1 */ create table t(id int primary key, v int);
/* s1 */ begin pessimistic;
/* s1 */ select * from t where id = 1 for update;
/* s1 */ insert into t values(1, 1);
/* s1 */ delete from t where id = 1;
/* s1 */ commit;
/* s1 */ select * from t; -- empty » curl http://127.0.0.1:10080/mvcc/index/test/t/primary/1\?id\=1
"key": "7480000000000000405F698000000000000001038000000000000001",
"region_id": 2,
"value": {
"info": {
"writes": [
{
"type": 1,
"start_ts": 428417554420072454,
"commit_ts": 428417554433179651
}
]
}
}
} With clustered-index on, the result is the same./* s1 */ drop table if exists t;
/* s1 */ set session tidb_enable_clustered_index = 'on';
/* s1 */ create table t(id int primary key, v int);
/* s1 */ begin pessimistic;
/* s1 */ select * from t where id = 1 for update;
/* s1 */ insert into t values(1, 1);
/* s1 */ delete from t where id = 1;
/* s1 */ commit;
/* s1 */ select * from t; » curl http://127.0.0.1:10080/mvcc/key/test/t/1
{
"key": "74800000000000003D5F728000000000000001",
"region_id": 2,
"value": {
"info": {
"writes": [
{
"type": 1,
"start_ts": 428417709446791174,
"commit_ts": 428417709446791177
}
]
}
}
} Because when adding a pessimistic lock, the node for the index key will is allocated. |
Good catch, I'm thinking about the solution, how to accurately identify the newly inserted value which must not exist in storage. |
fc2a818
to
315aa95
Compare
315aa95
to
eed0dff
Compare
eed0dff
to
e46ec19
Compare
/run-all-tests |
@@ -5813,3 +5813,51 @@ func (s *testSessionSuite) TestSameNameObjectWithLocalTemporaryTable(c *C) { | |||
" `cs1` int(11) DEFAULT NULL\n" + | |||
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin")) | |||
} | |||
|
|||
func (s *testSessionSuite) TestOptimizedDeleteYourWrites(c *C) { |
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 this test also passes without optimization of delete your writes.
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 used to verify the optimization would not break consistency. To verify if the dangling delete
is optimized, we may need to check the mvcc version and such test cases are easier to implement in utf.
sessionctx/stmtctx/stmtctx.go
Outdated
@@ -197,6 +197,9 @@ type StatementContext struct { | |||
EnableOptimizeTrace bool | |||
// LogicalOptimizeTrace indicates the trace for optimize | |||
LogicalOptimizeTrace *tracing.LogicalOptimizeTracer | |||
// IsNewlyInserted indicates the current statement is inserting new rows. This flag will be | |||
// used to optimize the `delete-your-write` situation. | |||
IsNewlyInserted bool |
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.
Does this flag need to be reset when a new statement comes?
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 needed, a new statement may create a new stmtCtx
object, but for StatementContext.ResetForRetry
, seems we still need to reset it there?
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.
Is the flag only for passing value from AddRecord
to index.Create
? I didn't understand 😕 What if insert on duplicate update
two records, one of which already exists?
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, as the index.Create
could be used by different upper functions such as ReBuildIndex
we need to find out a way to classify if we are creating newly inserted index keys.
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.
Is the flag only for passing value from
AddRecord
toindex.Create
? I didn't under stand 😕 What ifinsert on duplicate update
two records, one of which already exists?
Seems there's still some problems and it's not statement level flag and should be row level, thanks for reminding.
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.
@you06 @MyonKeminta
PTAL again, the stmtCtx
is removed and create options is used so that the affect is not statement level.
err = txn.GetMemBuffer().SetWithFlags(key, idxVal, kv.SetPresumeKeyNotExists, kv.SetNewlyInserted) | ||
} else { | ||
err = txn.GetMemBuffer().SetWithFlags(key, idxVal, kv.SetPresumeKeyNotExists) | ||
} |
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 in such a table:
create table t (id int primary key, v int, unique index (v));
insert into t values (1, 10);
If we execute:
begin;
delete from t where id = 1;
insert into t values (2, 10);
delete from t where id = 2;
commit;
Is it possible that the unique key is regarded as a delete-your-write and does noop on this transaction, results in the index key being left not deleted?
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 newlyInserted
flag is used with presumeNotExist
flag which ensures the targe key does not exist both in memdb
and the store. If the unique key is deleted first, the get operation in memdb
will return zero length value and a nil error. So the flag will not use for this case.
ce45f7c
to
3f1bce8
Compare
@cfzjywxk: PR needs rebase. 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 kubernetes/test-infra repository. |
@cfzjywxk: The following tests failed, say
Full PR test history. Your PR dashboard. 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 kubernetes/test-infra repository. I understand the commands that are listed here. |
What problem does this PR solve?
Issue Number:
Related to #27564
Problem Summary:
The transaction mutation generation is incompatible with each other for different situations like optimistic/pessimistic transactions with constraint check in place or not.
What is changed and how it works?
What's Changed:
Try to use key node marks to differentiate the keys newly inserted and then deleted, see the comments in the issue above for details.
How it Works:
Check List
Tests
Side effects
Documentation
Release note