diff --git a/session/tidb_test.go b/session/tidb_test.go index 4c854b4b66354..30f16171ae4cf 100644 --- a/session/tidb_test.go +++ b/session/tidb_test.go @@ -75,7 +75,8 @@ func TestKeysNeedLock(t *testing.T) { t.Parallel() rowKey := tablecodec.EncodeRowKeyWithHandle(1, kv.IntHandle(1)) - indexKey := tablecodec.EncodeIndexSeekKey(1, 1, []byte{1}) + uniqueIndexKey := tablecodec.EncodeIndexSeekKey(1, 1, []byte{1}) + nonUniqueIndexKey := tablecodec.EncodeIndexSeekKey(1, 2, []byte{1}) uniqueValue := make([]byte, 8) uniqueUntouched := append(uniqueValue, '1') nonUniqueVal := []byte{'0'} @@ -89,18 +90,20 @@ func TestKeysNeedLock(t *testing.T) { }{ {rowKey, rowVal, true}, {rowKey, deleteVal, true}, - {indexKey, nonUniqueVal, false}, - {indexKey, nonUniqueUntouched, false}, - {indexKey, uniqueValue, true}, - {indexKey, uniqueUntouched, false}, - {indexKey, deleteVal, false}, + {nonUniqueIndexKey, nonUniqueVal, false}, + {nonUniqueIndexKey, nonUniqueUntouched, false}, + {uniqueIndexKey, uniqueValue, true}, + {uniqueIndexKey, uniqueUntouched, false}, + {uniqueIndexKey, deleteVal, false}, } for _, test := range tests { - require.Equal(t, test.need, keyNeedToLock(test.key, test.val, 0)) - } + need := keyNeedToLock(test.key, test.val, 0) + require.Equal(t, test.need, need) - flag := kv.KeyFlags(1) - require.True(t, flag.HasPresumeKeyNotExists()) - require.True(t, keyNeedToLock(indexKey, deleteVal, flag)) + flag := kv.KeyFlags(1) + need = keyNeedToLock(test.key, test.val, flag) + require.True(t, flag.HasPresumeKeyNotExists()) + require.True(t, need) + } } diff --git a/session/txn.go b/session/txn.go index d2b57f08cb792..17913b8ac5d8d 100644 --- a/session/txn.go +++ b/session/txn.go @@ -447,9 +447,12 @@ func keyNeedToLock(k, v []byte, flags kv.KeyFlags) bool { if tablecodec.IsUntouchedIndexKValue(k, v) { return false } - isNonUniqueIndex := tablecodec.IsIndexKey(k) && len(v) == 1 - // Put row key and unique index need to lock. - return !isNonUniqueIndex + + if !tablecodec.IsIndexKey(k) { + return true + } + + return tablecodec.IndexKVIsUnique(v) } func getBinlogMutation(ctx sessionctx.Context, tableID int64) *binlog.TableMutation { diff --git a/tablecodec/tablecodec.go b/tablecodec/tablecodec.go index 79c73713583e1..fff125b151bb1 100644 --- a/tablecodec/tablecodec.go +++ b/tablecodec/tablecodec.go @@ -1526,3 +1526,16 @@ func decodeIndexKvGeneral(key, value []byte, colsLen int, hdStatus HandleStatus, } return resultValues, nil } + +// IndexKVIsUnique uses to judge if an index is unique, it can handle the KV committed by txn already, it doesn't consider the untouched flag. +func IndexKVIsUnique(value []byte) bool { + if len(value) <= MaxOldEncodeValueLen { + return len(value) == 8 + } + if getIndexVersion(value) == 1 { + segs := SplitIndexValueForClusteredIndexVersion1(value) + return segs.CommonHandle != nil + } + segs := SplitIndexValue(value) + return segs.IntHandle != nil || segs.CommonHandle != nil +}