diff --git a/DEPS.bzl b/DEPS.bzl index 1831a0cc03abb..5245f63c829ee 100644 --- a/DEPS.bzl +++ b/DEPS.bzl @@ -3703,8 +3703,8 @@ def go_deps(): name = "com_github_tikv_client_go_v2", build_file_proto_mode = "disable_global", importpath = "github.com/tikv/client-go/v2", - sum = "h1:tayF5Szzeemsrgmup5dh5Uom4BiwzmYTMQ84NdrA+68=", - version = "v2.0.4-0.20230918031736-9126d0716e90", + sum = "h1:x4x8yO7tHtxOepMGpPnnLMVw2geDsrYbbbB7k+0zusY=", + version = "v2.0.4-0.20231020030327-4ecf7c282e37", ) go_repository( name = "com_github_tikv_pd_client", diff --git a/executor/executor_failpoint_test.go b/executor/executor_failpoint_test.go index c6eebfcdb7845..bc5ee84a000cc 100644 --- a/executor/executor_failpoint_test.go +++ b/executor/executor_failpoint_test.go @@ -28,9 +28,11 @@ import ( "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/ddl" "github.com/pingcap/tidb/executor" + "github.com/pingcap/tidb/meta" "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/store/copr" + "github.com/pingcap/tidb/store/helper" "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/util/deadlockhistory" "github.com/stretchr/testify/require" @@ -622,3 +624,31 @@ func TestTiKVClientReadTimeout(t *testing.T) { explain = fmt.Sprintf("%v", rows[0]) require.Regexp(t, ".*TableReader.* root time:.*, loops:.* cop_task: {num: 1, .* rpc_num: 2.*", explain) } + +func TestGetMvccByEncodedKeyRegionError(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + h := helper.NewHelper(store.(helper.Storage)) + txn, err := store.Begin() + require.NoError(t, err) + m := meta.NewMeta(txn) + schemaVersion := tk.Session().GetDomainInfoSchema().SchemaMetaVersion() + key := m.EncodeSchemaDiffKey(schemaVersion) + + resp, err := h.GetMvccByEncodedKey(key) + require.NoError(t, err) + require.NotNil(t, resp.Info) + require.Equal(t, 1, len(resp.Info.Writes)) + require.Less(t, uint64(0), resp.Info.Writes[0].CommitTs) + commitTs := resp.Info.Writes[0].CommitTs + + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/store/mockstore/unistore/epochNotMatch", "1*return(true)")) + defer func() { + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/store/mockstore/unistore/epochNotMatch")) + }() + resp, err = h.GetMvccByEncodedKey(key) + require.NoError(t, err) + require.NotNil(t, resp.Info) + require.Equal(t, 1, len(resp.Info.Writes)) + require.Equal(t, commitTs, resp.Info.Writes[0].CommitTs) +} diff --git a/go.mod b/go.mod index 5551ae82db3c3..f0a5d80949f0e 100644 --- a/go.mod +++ b/go.mod @@ -90,8 +90,8 @@ require ( github.com/stretchr/testify v1.8.0 github.com/tdakkota/asciicheck v0.1.1 github.com/tiancaiamao/appdash v0.0.0-20181126055449-889f96f722a2 - github.com/tikv/client-go/v2 v2.0.4-0.20230918062126-32c4ef54d6ed - github.com/tikv/pd/client v0.0.0-20230904040343-947701a32c05 + github.com/tikv/client-go/v2 v2.0.4-0.20231020030327-4ecf7c282e37 + github.com/tikv/pd/client v0.0.0-20230904040343-947701a32c05 github.com/timakin/bodyclose v0.0.0-20210704033933-f49887972144 github.com/twmb/murmur3 v1.1.3 github.com/uber/jaeger-client-go v2.22.1+incompatible diff --git a/go.sum b/go.sum index e5a85424edc56..654db15fdf20c 100644 --- a/go.sum +++ b/go.sum @@ -935,8 +935,8 @@ github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3 h1:f+jULpR github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY= github.com/tiancaiamao/appdash v0.0.0-20181126055449-889f96f722a2 h1:mbAskLJ0oJfDRtkanvQPiooDH8HvJ2FBh+iKT/OmiQQ= github.com/tiancaiamao/appdash v0.0.0-20181126055449-889f96f722a2/go.mod h1:2PfKggNGDuadAa0LElHrByyrz4JPZ9fFx6Gs7nx7ZZU= -github.com/tikv/client-go/v2 v2.0.4-0.20230918062126-32c4ef54d6ed h1:O3MQ1ucUSsH8jTalvX98NZk66YCaxSABRp5UgcPenIc= -github.com/tikv/client-go/v2 v2.0.4-0.20230918062126-32c4ef54d6ed/go.mod h1:mmVCLP2OqWvQJPOIevQPZvGphzh/oq9vv8J5LDfpadQ= +github.com/tikv/client-go/v2 v2.0.4-0.20231020030327-4ecf7c282e37 h1:x4x8yO7tHtxOepMGpPnnLMVw2geDsrYbbbB7k+0zusY= +github.com/tikv/client-go/v2 v2.0.4-0.20231020030327-4ecf7c282e37/go.mod h1:mmVCLP2OqWvQJPOIevQPZvGphzh/oq9vv8J5LDfpadQ= github.com/tikv/pd/client v0.0.0-20230904040343-947701a32c05 h1:e4hLUKfgfPeJPZwOfU+/I/03G0sn6IZqVcbX/5o+hvM= github.com/tikv/pd/client v0.0.0-20230904040343-947701a32c05/go.mod h1:MLIl+d2WbOF4A3U88WKtyXrQQW417wZDDvBcq2IW9bQ= github.com/timakin/bodyclose v0.0.0-20210704033933-f49887972144 h1:kl4KhGNsJIbDHS9/4U9yQo1UcPQM0kOMJHn29EoH/Ro= diff --git a/store/helper/helper.go b/store/helper/helper.go index 1b077dcec8843..28276d050953b 100644 --- a/store/helper/helper.go +++ b/store/helper/helper.go @@ -96,23 +96,46 @@ func NewHelper(store Storage) *Helper { // GetMvccByEncodedKey get the MVCC value by the specific encoded key. func (h *Helper) GetMvccByEncodedKey(encodedKey kv.Key) (*kvrpcpb.MvccGetByKeyResponse, error) { - keyLocation, err := h.RegionCache.LocateKey(tikv.NewBackofferWithVars(context.Background(), 500, nil), encodedKey) - if err != nil { - return nil, derr.ToTiDBErr(err) - } - + bo := tikv.NewBackofferWithVars(context.Background(), 5000, nil) tikvReq := tikvrpc.NewRequest(tikvrpc.CmdMvccGetByKey, &kvrpcpb.MvccGetByKeyRequest{Key: encodedKey}) - kvResp, err := h.Store.SendReq(tikv.NewBackofferWithVars(context.Background(), 500, nil), tikvReq, keyLocation.Region, time.Minute) - if err != nil { - logutil.BgLogger().Info("get MVCC by encoded key failed", - zap.Stringer("encodeKey", encodedKey), - zap.Reflect("region", keyLocation.Region), - zap.Stringer("keyLocation", keyLocation), - zap.Reflect("kvResp", kvResp), - zap.Error(err)) - return nil, errors.Trace(err) + for { + keyLocation, err := h.RegionCache.LocateKey(bo, encodedKey) + if err != nil { + return nil, derr.ToTiDBErr(err) + } + + kvResp, err := h.Store.SendReq(bo, tikvReq, keyLocation.Region, time.Minute) + if err != nil { + logutil.BgLogger().Info("get MVCC by encoded key failed", + zap.Stringer("encodeKey", encodedKey), + zap.Reflect("region", keyLocation.Region), + zap.Stringer("keyLocation", keyLocation), + zap.Reflect("kvResp", kvResp), + zap.Error(err)) + return nil, errors.Trace(err) + } + regionErr, err := kvResp.GetRegionError() + if err != nil { + return nil, errors.Trace(err) + } + if regionErr != nil { + if err = bo.Backoff(tikv.BoRegionMiss(), errors.New(regionErr.String())); err != nil { + return nil, err + } + continue + } + mvccResp := kvResp.Resp.(*kvrpcpb.MvccGetByKeyResponse) + if errMsg := mvccResp.GetError(); errMsg != "" { + logutil.BgLogger().Info("get MVCC by encoded key failed", + zap.Stringer("encodeKey", encodedKey), + zap.Reflect("region", keyLocation.Region), + zap.Stringer("keyLocation", keyLocation), + zap.Reflect("kvResp", kvResp), + zap.String("error", errMsg)) + return nil, errors.New(errMsg) + } + return mvccResp, nil } - return kvResp.Resp.(*kvrpcpb.MvccGetByKeyResponse), nil } // MvccKV wraps the key's mvcc info in tikv. diff --git a/store/mockstore/unistore/rpc.go b/store/mockstore/unistore/rpc.go index 44a44e5985751..f4dd71f503258 100644 --- a/store/mockstore/unistore/rpc.go +++ b/store/mockstore/unistore/rpc.go @@ -66,6 +66,11 @@ func (c *RPCClient) SendRequest(ctx context.Context, addr string, req *tikvrpc.R failpoint.Return(tikvrpc.GenRegionErrorResp(req, &errorpb.Error{ServerIsBusy: &errorpb.ServerIsBusy{}})) } }) + failpoint.Inject("epochNotMatch", func(val failpoint.Value) { + if val.(bool) { + failpoint.Return(tikvrpc.GenRegionErrorResp(req, &errorpb.Error{EpochNotMatch: &errorpb.EpochNotMatch{}})) + } + }) failpoint.Inject("unistoreRPCClientSendHook", func(val failpoint.Value) { if val.(bool) && UnistoreRPCClientSendHook != nil {