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

transaction: lock unique key for delete operation (#19220) #20705

Merged
merged 17 commits into from
Nov 3, 2020

Conversation

ti-srebot
Copy link
Contributor

cherry-pick #19220 to release-4.0


What problem does this PR solve?

Issue Number: close #18798, close #20535

Problem Summary:

What is changed and how it works?

What's Changed:

Lock index for delete operation, so that some transactions can be serialized.

Related changes

  • Need to cherry-pick to the release branch

Check List

Tests

  • Unit test

Release note

  • No release note

Signed-off-by: ti-srebot <ti-srebot@pingcap.com>
@ti-srebot
Copy link
Contributor Author

/run-all-tests

you06 added 5 commits October 29, 2020 15:19
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>
Signed-off-by: you06 <you1474600@gmail.com>
@you06
Copy link
Contributor

you06 commented Oct 29, 2020

/run-all-tests

Signed-off-by: you06 <you1474600@gmail.com>
@you06
Copy link
Contributor

you06 commented Oct 29, 2020

/run-all-tests

you06 added 2 commits October 30, 2020 11:44
Signed-off-by: you06 <you1474600@gmail.com>
Signed-off-by: you06 <you1474600@gmail.com>
@you06
Copy link
Contributor

you06 commented Oct 30, 2020

/run-all-tests

Copy link
Contributor

@bobotu bobotu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

session/txn.go Outdated
@@ -428,7 +434,7 @@ func (st *TxnState) KeysNeedToLock() ([]kv.Key, error) {
}
keys := make([]kv.Key, 0, st.stmtBufLen())
if err := kv.WalkMemBuffer(st.stmtBuf, func(k kv.Key, v []byte) error {
if !keyNeedToLock(k, v) {
if !st.stmtBuf.IfKeyNeedLock(k) && !keyNeedToLock(k, v) {
Copy link
Contributor

@bobotu bobotu Oct 30, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stmtBuf shared the same needLockKey map with txnBuf. After RollbackStmt the new keys added into stmtBuf.needLockKey will not be removed.

But it will not cause correctness issue:

  • If the key still existed after retry, it will be locked;
  • Otherwise, it will not be collected at here.

Maybe it will lock more keys than need in some scenarios? But this way seems much simpler than implementing a rollbackable needLockKey.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is MemBuffer.Discard called when rollback? Seems we can move needLockKey into Sandbox, then we can rollback it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep. I have already done something simliar as a part of #18372.

tidb/kv/memdb.go

Lines 32 to 71 in 761a961

type KeyFlags uint8
const (
flagPresumeKeyNotExists KeyFlags = 1 << iota
// flagTouched is a internal flag to help `Mark` operation.
// The default value of `KeyFlags` is 0 and the flags returned by any operation will set `flagTouched`.
// When merge two flags, if the newer one haven't set the `flagTouched`, the newer value will be ignored.
flagTouched KeyFlags = 0x80
)
// MarkPresumeKeyNotExists marks the existence of the associated key is checked lazily.
func (m KeyFlags) MarkPresumeKeyNotExists() KeyFlags {
return (m | flagPresumeKeyNotExists) | flagTouched
}
// UnmarkPresumeKeyNotExists reverts MarkPresumeKeyNotExists.
func (m KeyFlags) UnmarkPresumeKeyNotExists() KeyFlags {
return (m & ^flagPresumeKeyNotExists) | flagTouched
}
// HasPresumeKeyNotExists retruns whether the associated key use lazy check.
func (m KeyFlags) HasPresumeKeyNotExists() bool {
return m&flagPresumeKeyNotExists != 0
}
func (m KeyFlags) isTouched() bool {
return m&flagTouched != 0
}
// Merge used to merge two KeyFlags.
func (m KeyFlags) Merge(old KeyFlags) KeyFlags {
// Only consider flagPresumeKeyNotExists in merge operation for now.
// We should always respect to the older setting,
// the delete operation will overwrite flags in root tree instead of invoke merge.
if old.isTouched() {
return old
}
return m
}

x.flags = flags

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll try it following your implementation in the master.

Copy link
Contributor

@cfzjywxk cfzjywxk Oct 31, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better not to share objects in stmtbuf with txnBuf, we need make sure no unwanted keys get locked, or there will be other incompatbile behaviours issues.

@ti-srebot ti-srebot added the status/LGT1 Indicates that a PR has LGTM 1. label Oct 30, 2020
@@ -188,7 +188,7 @@ func (s *testMainSuite) TestKeysNeedLock(c *C) {
need bool
}{
{rowKey, rowVal, true},
{rowKey, deleteVal, true},
{rowKey, deleteVal, false},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Old deleted row keys need to be locked.

@@ -214,6 +214,15 @@ func (txn *tikvTxn) Delete(k kv.Key) error {
return txn.us.Delete(k)
}

func (txn *tikvTxn) DeleteWithNeedLock(k kv.Key) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems we will not use this path?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'd better write this method explicitly, otherwise, the txn.dirty may incorrect.

session/txn.go Outdated
@@ -428,7 +434,7 @@ func (st *TxnState) KeysNeedToLock() ([]kv.Key, error) {
}
keys := make([]kv.Key, 0, st.stmtBufLen())
if err := kv.WalkMemBuffer(st.stmtBuf, func(k kv.Key, v []byte) error {
if !keyNeedToLock(k, v) {
if !st.stmtBuf.IfKeyNeedLock(k) && !keyNeedToLock(k, v) {
Copy link
Contributor

@cfzjywxk cfzjywxk Oct 31, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better not to share objects in stmtbuf with txnBuf, we need make sure no unwanted keys get locked, or there will be other incompatbile behaviours issues.

tk2.MustExec(t.tk2Stmt)
doneCh <- struct{}{}
}()
time.Sleep(20 * time.Millisecond)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit short, may not be stable.

Signed-off-by: you06 <you1474600@gmail.com>
func (m *memDbBuffer) IfKeyNeedLock(k Key) bool {
_, ok := m.needLockKey[k.String()]
return ok
//m.needLockKey[k.String()] = struct{}{}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delete this line.

@cfzjywxk cfzjywxk modified the milestones: v4.0.8, v4.0.9 Oct 31, 2020
you06 added 3 commits October 31, 2020 14:54
Signed-off-by: you06 <you1474600@gmail.com>
Signed-off-by: you06 <you1474600@gmail.com>
@bobotu
Copy link
Contributor

bobotu commented Oct 31, 2020

LGTM

@you06
Copy link
Contributor

you06 commented Oct 31, 2020

/run-all-tests

@cfzjywxk
Copy link
Contributor

LGTM

@ti-srebot ti-srebot added status/LGT2 Indicates that a PR has LGTM 2. and removed status/LGT1 Indicates that a PR has LGTM 1. labels Oct 31, 2020
@@ -475,6 +508,7 @@ func (ms *mergeState) calculateRecomputeHeight(key []byte, sb *Sandbox) int {
}

type nodeHeader struct {
flags KeyFlags
height uint16
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we can reduce height to uint8, it'll be more memory friendly.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tidb/kv/sandbox.go

Lines 503 to 508 in 761a961

type nodeHeader struct {
height uint8
flags KeyFlags
keyLen uint16
valLen uint32
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Afraid of the overflow risk.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never overflow. The upper bound is

maxHeight = 16

Signed-off-by: you06 <you1474600@gmail.com>
@you06
Copy link
Contributor

you06 commented Oct 31, 2020

/run-all-tests

@you06
Copy link
Contributor

you06 commented Nov 2, 2020

@cfzjywxk I think this PR can be merged now.

Copy link
Member

@coocood coocood left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@ti-srebot ti-srebot added status/LGT3 The PR has already had 3 LGTM. and removed status/LGT2 Indicates that a PR has LGTM 2. labels Nov 2, 2020
@wjhuang2016 wjhuang2016 removed the sig/sql-infra SIG: SQL Infra label Nov 3, 2020
@github-actions github-actions bot added the sig/sql-infra SIG: SQL Infra label Nov 3, 2020
@you06
Copy link
Contributor

you06 commented Nov 3, 2020

What's wrong with the action :(

@cfzjywxk
Copy link
Contributor

cfzjywxk commented Nov 3, 2020

/merge

@ti-srebot
Copy link
Contributor Author

Your auto merge job has been accepted, waiting for:

  • 20356

@ti-srebot ti-srebot added the status/can-merge Indicates a PR has been approved by a committer. label Nov 3, 2020
@ti-srebot
Copy link
Contributor Author

/run-all-tests

@ti-srebot ti-srebot merged commit b77153d into pingcap:release-4.0 Nov 3, 2020
@you06 you06 removed the sig/sql-infra SIG: SQL Infra label Nov 3, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
sig/execution SIG execution sig/transaction SIG:Transaction status/can-merge Indicates a PR has been approved by a committer. status/LGT3 The PR has already had 3 LGTM. type/4.0-cherry-pick
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants