Skip to content

Commit

Permalink
transaction: always lock keys with presume not exists flag (#19071)
Browse files Browse the repository at this point in the history
* transaction: lock delete unique index key

* always lock for key with presume not exists flag

Co-authored-by: ti-srebot <66930949+ti-srebot@users.noreply.github.com>
  • Loading branch information
coocood and ti-srebot authored Aug 9, 2020
1 parent 07ae607 commit b75a30f
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 3 deletions.
11 changes: 11 additions & 0 deletions executor/write_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"github.com/pingcap/tidb/types"
"github.com/pingcap/tidb/util/mock"
"github.com/pingcap/tidb/util/testkit"
"github.com/pingcap/tidb/util/testutil"
)

type testBypassSuite struct{}
Expand Down Expand Up @@ -836,6 +837,16 @@ func (s *testSuite4) TestInsertOnDupUpdateDefault(c *C) {
tk.MustGetErrCode("insert into t2 values (4,default,default) on duplicate key update a=default(a), c=default(c);", mysql.ErrBadGeneratedColumn)
tk.MustGetErrCode("insert into t2 values (4,default,default) on duplicate key update a=default(a), c=default(a);", mysql.ErrBadGeneratedColumn)
tk.MustExec("drop table t1, t2")

tk.MustExec("set @@tidb_txn_mode = 'pessimistic'")
tk.MustExec("create table t ( c_int int, c_string varchar(40) collate utf8mb4_bin , primary key (c_string), unique key (c_int));")
tk.MustExec("insert into t values (22, 'gold witch'), (24, 'gray singer'), (21, 'silver sight');")
tk.MustExec("begin;")
err := tk.ExecToErr("insert into t values (21,'black warlock'), (22, 'dark sloth'), (21, 'cyan song') on duplicate key update c_int = c_int + 1, c_string = concat(c_int, ':', c_string);")
c.Assert(kv.ErrKeyExists.Equal(err), IsTrue)
tk.MustExec("commit;")
tk.MustQuery("select * from t order by c_int;").Check(testutil.RowsWithSep("|", "21|silver sight", "22|gold witch", "24|gray singer"))
tk.MustExec("drop table t;")
}

func (s *testSuite4) TestReplace(c *C) {
Expand Down
5 changes: 4 additions & 1 deletion session/tidb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,9 @@ func (s *testMainSuite) TestKeysNeedLock(c *C) {
{indexKey, deleteVal, false},
}
for _, tt := range tests {
c.Assert(keyNeedToLock(tt.key, tt.val), Equals, tt.need)
c.Assert(keyNeedToLock(tt.key, tt.val, 0), Equals, tt.need)
}
flag := kv.KeyFlags(1)
c.Assert(flag.HasPresumeKeyNotExists(), IsTrue)
c.Assert(keyNeedToLock(indexKey, deleteVal, flag), IsTrue)
}
7 changes: 5 additions & 2 deletions session/txn.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,20 +294,23 @@ func (st *TxnState) KeysNeedToLock() ([]kv.Key, error) {
keys := make([]kv.Key, 0, st.countHint())
buf := st.Transaction.GetMemBuffer()
buf.InspectStage(st.stagingHandle, func(k kv.Key, flags kv.KeyFlags, v []byte) {
if !keyNeedToLock(k, v) {
if !keyNeedToLock(k, v, flags) {
return
}
keys = append(keys, k)
})
return keys, nil
}

func keyNeedToLock(k, v []byte) bool {
func keyNeedToLock(k, v []byte, flags kv.KeyFlags) bool {
isTableKey := bytes.HasPrefix(k, tablecodec.TablePrefix())
if !isTableKey {
// meta key always need to lock.
return true
}
if flags.HasPresumeKeyNotExists() {
return true
}
isDelete := len(v) == 0
if isDelete {
// only need to delete row key.
Expand Down

0 comments on commit b75a30f

Please sign in to comment.