From 4d33125bd3735d90f68240e8c935a54ad271bd4c Mon Sep 17 00:00:00 2001 From: qupeng Date: Thu, 13 Feb 2020 10:42:44 +0800 Subject: [PATCH 1/5] session: support leader-and-follower for tidb_replica_read Signed-off-by: qupeng --- go.sum | 1 + kv/kv.go | 6 +++--- sessionctx/variable/session.go | 2 ++ sessionctx/variable/varsutil.go | 2 ++ sessionctx/variable/varsutil_test.go | 5 +++++ store/tikv/region_cache.go | 32 ++++++++++++++++++++++++++++ 6 files changed, 45 insertions(+), 3 deletions(-) diff --git a/go.sum b/go.sum index efc750da159d9..606dc5b313e52 100644 --- a/go.sum +++ b/go.sum @@ -427,6 +427,7 @@ gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bl gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3 h1:fvjTMHxHEw/mxHbtzPi3JCcKXQRAnQTBRo6YCJSVHKI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/kv/kv.go b/kv/kv.go index e7906c73242b4..83cc44d79240f 100644 --- a/kv/kv.go +++ b/kv/kv.go @@ -93,13 +93,13 @@ const ( ReplicaReadLeader ReplicaReadType = 1 << iota // ReplicaReadFollower stands for 'read from follower'. ReplicaReadFollower - // ReplicaReadLearner stands for 'read from learner'. - ReplicaReadLearner + // ReplicaReadMixed stands for 'read from leader and follower and learner'. + ReplicaReadMixed ) // IsFollowerRead checks if leader is going to be used to read data. func (r ReplicaReadType) IsFollowerRead() bool { - return r == ReplicaReadFollower + return r != ReplicaReadLeader } // Those limits is enforced to make sure the transaction can be well handled by TiKV. diff --git a/sessionctx/variable/session.go b/sessionctx/variable/session.go index 26de64cead630..94ebe17d1e66c 100644 --- a/sessionctx/variable/session.go +++ b/sessionctx/variable/session.go @@ -1115,6 +1115,8 @@ func (s *SessionVars) SetSystemVar(name string, val string) error { case TiDBReplicaRead: if strings.EqualFold(val, "follower") { s.SetReplicaRead(kv.ReplicaReadFollower) + } else if strings.EqualFold(val, "leader-and-follower") { + s.SetReplicaRead(kv.ReplicaReadMixed) } else if strings.EqualFold(val, "leader") || len(val) == 0 { s.SetReplicaRead(kv.ReplicaReadLeader) } diff --git a/sessionctx/variable/varsutil.go b/sessionctx/variable/varsutil.go index 692f89303208d..99419dafebb39 100644 --- a/sessionctx/variable/varsutil.go +++ b/sessionctx/variable/varsutil.go @@ -617,6 +617,8 @@ func ValidateSetSystemVar(vars *SessionVars, name string, value string) (string, case TiDBReplicaRead: if strings.EqualFold(value, "follower") { return "follower", nil + } else if strings.EqualFold(value, "leader-and-follower") { + return "leader-and-follower", nil } else if strings.EqualFold(value, "leader") || len(value) == 0 { return "leader", nil } diff --git a/sessionctx/variable/varsutil_test.go b/sessionctx/variable/varsutil_test.go index c2791a2439582..c0213f02f6e45 100644 --- a/sessionctx/variable/varsutil_test.go +++ b/sessionctx/variable/varsutil_test.go @@ -379,6 +379,11 @@ func (s *testVarsutilSuite) TestVarsutil(c *C) { c.Assert(err, IsNil) c.Assert(val, Equals, "leader") c.Assert(v.GetReplicaRead(), Equals, kv.ReplicaReadLeader) + SetSessionSystemVar(v, TiDBReplicaRead, types.NewStringDatum("leader-and-follower")) + val, err = GetSessionSystemVar(v, TiDBReplicaRead) + c.Assert(err, IsNil) + c.Assert(val, Equals, "leader-and-follower") + c.Assert(v.GetReplicaRead(), Equals, kv.ReplicaReadMixed) SetSessionSystemVar(v, TiDBEnableStmtSummary, types.NewStringDatum("on")) val, err = GetSessionSystemVar(v, TiDBEnableStmtSummary) diff --git a/store/tikv/region_cache.go b/store/tikv/region_cache.go index e89042e6b5e99..ab4242509dc08 100644 --- a/store/tikv/region_cache.go +++ b/store/tikv/region_cache.go @@ -115,6 +115,31 @@ func (r *RegionStore) follower(seed uint32) int32 { return r.workTiKVIdx } +// return next leader or follower store's index +func (r *RegionStore) peer(seed uint32) int32 { + l := uint32(len(r.stores)) + if l <= 1 { + return r.workTiKVIdx + } + + candidates := make([]int32, 0, len(r.stores)) + for i := 0; i < len(r.stores); i++ { + if r.stores[i].storeType != kv.TiKV { + continue + } + if r.storeFails[i] != atomic.LoadUint32(&r.stores[i].fail) { + continue + } + candidates = append(candidates, int32(i)) + } + + if len(candidates) == 0 { + return r.workTiKVIdx + } else { + return int32(seed) % int32(len(candidates)) + } +} + // init initializes region after constructed. func (r *Region) init(c *RegionCache) { // region store pull used store from global store map @@ -306,6 +331,8 @@ func (c *RegionCache) GetTiKVRPCContext(bo *Backoffer, id RegionVerID, replicaRe switch replicaRead { case kv.ReplicaReadFollower: store, peer, storeIdx = cachedRegion.FollowerStorePeer(regionStore, followerStoreSeed) + case kv.ReplicaReadMixed: + store, peer, storeIdx = cachedRegion.AnyStorePeer(regionStore, followerStoreSeed) default: store, peer, storeIdx = cachedRegion.WorkStorePeer(regionStore) } @@ -1055,6 +1082,11 @@ func (r *Region) FollowerStorePeer(rs *RegionStore, followerStoreSeed uint32) (* return r.getStorePeer(rs, rs.follower(followerStoreSeed)) } +// AnyStorePeer returns a leader or follower store with the associated peer. +func (r *Region) AnyStorePeer(rs *RegionStore, followerStoreSeed uint32) (*Store, *metapb.Peer, int) { + return r.getStorePeer(rs, rs.peer(followerStoreSeed)) +} + // RegionVerID is a unique ID that can identify a Region at a specific version. type RegionVerID struct { id uint64 From ac1ce45563460d3094ce6153c75e3b81c70cef97 Mon Sep 17 00:00:00 2001 From: qupeng Date: Thu, 13 Feb 2020 11:07:53 +0800 Subject: [PATCH 2/5] more tests Signed-off-by: qupeng --- store/tikv/region_cache.go | 7 +--- store/tikv/region_cache_test.go | 62 +++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 6 deletions(-) diff --git a/store/tikv/region_cache.go b/store/tikv/region_cache.go index ab4242509dc08..600a5d18db54d 100644 --- a/store/tikv/region_cache.go +++ b/store/tikv/region_cache.go @@ -117,11 +117,6 @@ func (r *RegionStore) follower(seed uint32) int32 { // return next leader or follower store's index func (r *RegionStore) peer(seed uint32) int32 { - l := uint32(len(r.stores)) - if l <= 1 { - return r.workTiKVIdx - } - candidates := make([]int32, 0, len(r.stores)) for i := 0; i < len(r.stores); i++ { if r.stores[i].storeType != kv.TiKV { @@ -136,7 +131,7 @@ func (r *RegionStore) peer(seed uint32) int32 { if len(candidates) == 0 { return r.workTiKVIdx } else { - return int32(seed) % int32(len(candidates)) + return candidates[int32(seed)%int32(len(candidates))] } } diff --git a/store/tikv/region_cache_test.go b/store/tikv/region_cache_test.go index b39b541385ee0..adf164135cd21 100644 --- a/store/tikv/region_cache_test.go +++ b/store/tikv/region_cache_test.go @@ -944,6 +944,41 @@ func (s *testRegionCacheSuite) TestFollowerReadFallback(c *C) { c.Assert(ctx.Peer.Id, Equals, peer3) } +func (s *testRegionCacheSuite) TestMixedReadFallback(c *C) { + // 3 nodes and no.1 is leader. + store3 := s.cluster.AllocID() + peer3 := s.cluster.AllocID() + s.cluster.AddStore(store3, s.storeAddr(store3)) + s.cluster.AddPeer(s.region1, store3, peer3) + s.cluster.ChangeLeader(s.region1, s.peer1) + + loc, err := s.cache.LocateKey(s.bo, []byte("a")) + c.Assert(err, IsNil) + ctx, err := s.cache.GetTiKVRPCContext(s.bo, loc.Region, kv.ReplicaReadLeader, 0) + c.Assert(err, IsNil) + c.Assert(ctx.Peer.Id, Equals, s.peer1) + c.Assert(len(ctx.Meta.Peers), Equals, 3) + + // verify follower to be store1, store2 and store3 + ctxFollower1, err := s.cache.GetTiKVRPCContext(s.bo, loc.Region, kv.ReplicaReadMixed, 0) + c.Assert(err, IsNil) + c.Assert(ctxFollower1.Peer.Id, Equals, s.peer1) + + ctxFollower2, err := s.cache.GetTiKVRPCContext(s.bo, loc.Region, kv.ReplicaReadMixed, 1) + c.Assert(err, IsNil) + c.Assert(ctxFollower2.Peer.Id, Equals, s.peer2) + + ctxFollower3, err := s.cache.GetTiKVRPCContext(s.bo, loc.Region, kv.ReplicaReadMixed, 2) + c.Assert(err, IsNil) + c.Assert(ctxFollower3.Peer.Id, Equals, peer3) + + // send fail on store2, next follower read is going to fallback to store3 + s.cache.OnSendFail(s.bo, ctxFollower1, false, errors.New("test error")) + ctx, err = s.cache.GetTiKVRPCContext(s.bo, loc.Region, kv.ReplicaReadMixed, 0) + c.Assert(err, IsNil) + c.Assert(ctx.Peer.Id, Equals, s.peer2) +} + func (s *testRegionCacheSuite) TestFollowerMeetEpochNotMatch(c *C) { // 3 nodes and no.1 is region1 leader. store3 := s.cluster.AllocID() @@ -971,6 +1006,33 @@ func (s *testRegionCacheSuite) TestFollowerMeetEpochNotMatch(c *C) { c.Assert(followReqSeed, Equals, uint32(1)) } +func (s *testRegionCacheSuite) TestMixedMeetEpochNotMatch(c *C) { + // 3 nodes and no.1 is region1 leader. + store3 := s.cluster.AllocID() + peer3 := s.cluster.AllocID() + s.cluster.AddStore(store3, s.storeAddr(store3)) + s.cluster.AddPeer(s.region1, store3, peer3) + s.cluster.ChangeLeader(s.region1, s.peer1) + + // Check the two regions. + loc1, err := s.cache.LocateKey(s.bo, []byte("a")) + c.Assert(err, IsNil) + c.Assert(loc1.Region.id, Equals, s.region1) + + reqSend := NewRegionRequestSender(s.cache, nil) + + // follower read failed on store1 + followReqSeed := uint32(0) + ctxFollower1, err := s.cache.GetTiKVRPCContext(s.bo, loc1.Region, kv.ReplicaReadMixed, followReqSeed) + c.Assert(err, IsNil) + c.Assert(ctxFollower1.Peer.Id, Equals, s.peer1) + c.Assert(ctxFollower1.Store.storeID, Equals, s.store1) + + regionErr := &errorpb.Error{EpochNotMatch: &errorpb.EpochNotMatch{}} + reqSend.onRegionError(s.bo, ctxFollower1, &followReqSeed, regionErr) + c.Assert(followReqSeed, Equals, uint32(1)) +} + func createSampleRegion(startKey, endKey []byte) *Region { return &Region{ meta: &metapb.Region{ From 158fac93bbb4cde30a2982ce1ece03b7fc79de1c Mon Sep 17 00:00:00 2001 From: qupeng Date: Thu, 13 Feb 2020 11:11:57 +0800 Subject: [PATCH 3/5] make check Signed-off-by: qupeng --- go.sum | 6 ------ store/tikv/region_cache.go | 3 +-- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/go.sum b/go.sum index 606dc5b313e52..1dc3d816bc026 100644 --- a/go.sum +++ b/go.sum @@ -207,8 +207,6 @@ github.com/pingcap/goleveldb v0.0.0-20191226122134-f82aafb29989 h1:surzm05a8C9dN github.com/pingcap/goleveldb v0.0.0-20191226122134-f82aafb29989/go.mod h1:O17XtbryoCJhkKGbT62+L2OlrniwqiGLSqrmdHCMzZw= github.com/pingcap/kvproto v0.0.0-20191211054548-3c6b38ea5107/go.mod h1:WWLmULLO7l8IOcQG+t+ItJ3fEcrL5FxF0Wu+HrMy26w= github.com/pingcap/kvproto v0.0.0-20191213111810-93cb7c623c8b/go.mod h1:WWLmULLO7l8IOcQG+t+ItJ3fEcrL5FxF0Wu+HrMy26w= -github.com/pingcap/kvproto v0.0.0-20200108025604-a4dc183d2af5 h1:RUxQExD5yubAjWGnw8kcxfO9abbiVHIE1rbuCyQCWDE= -github.com/pingcap/kvproto v0.0.0-20200108025604-a4dc183d2af5/go.mod h1:WWLmULLO7l8IOcQG+t+ItJ3fEcrL5FxF0Wu+HrMy26w= github.com/pingcap/kvproto v0.0.0-20200210234432-a965739f8162 h1:lsoIoCoXMpcHvW6jHcqP/prA4I6duAp1DVyG2ULz4bM= github.com/pingcap/kvproto v0.0.0-20200210234432-a965739f8162/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= github.com/pingcap/log v0.0.0-20191012051959-b742a5d432e9 h1:AJD9pZYm72vMgPcQDww9rkZ1DnWfl0pXV3BOWlkYIjA= @@ -347,8 +345,6 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190909003024-a7b16738d86b h1:XfVGCX+0T4WOStkaOsJRllbsiImhB2jgVBGc9L0lPGc= -golang.org/x/net v0.0.0-20190909003024-a7b16738d86b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191002035440-2ec189313ef0 h1:2mqDk8w/o6UmeUCu5Qiq2y7iMf6anbx+YA8d1JFoFrs= golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -396,8 +392,6 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20181004005441-af9cb2a35e7f/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190905072037-92dd089d5514 h1:oFSK4421fpCKRrpzIpybyBVWyht05NegY9+L/3TLAZs= -google.golang.org/genproto v0.0.0-20190905072037-92dd089d5514/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c h1:hrpEMCZ2O7DR5gC1n2AJGVhrwiEjOi35+jxtIuZpTMo= google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/grpc v0.0.0-20180607172857-7a6a684ca69e/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= diff --git a/store/tikv/region_cache.go b/store/tikv/region_cache.go index 600a5d18db54d..6cb37c9cf64ad 100644 --- a/store/tikv/region_cache.go +++ b/store/tikv/region_cache.go @@ -130,9 +130,8 @@ func (r *RegionStore) peer(seed uint32) int32 { if len(candidates) == 0 { return r.workTiKVIdx - } else { - return candidates[int32(seed)%int32(len(candidates))] } + return candidates[int32(seed)%int32(len(candidates))] } // init initializes region after constructed. From 55ddc67911703d2dda9ce45f730c5aba319331b4 Mon Sep 17 00:00:00 2001 From: qupeng Date: Fri, 14 Feb 2020 14:07:33 +0800 Subject: [PATCH 4/5] rebase go.sum Signed-off-by: qupeng --- go.sum | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/go.sum b/go.sum index d16df910d9dcf..41cd4ca2e99d8 100644 --- a/go.sum +++ b/go.sum @@ -207,6 +207,8 @@ github.com/pingcap/goleveldb v0.0.0-20191226122134-f82aafb29989 h1:surzm05a8C9dN github.com/pingcap/goleveldb v0.0.0-20191226122134-f82aafb29989/go.mod h1:O17XtbryoCJhkKGbT62+L2OlrniwqiGLSqrmdHCMzZw= github.com/pingcap/kvproto v0.0.0-20191211054548-3c6b38ea5107/go.mod h1:WWLmULLO7l8IOcQG+t+ItJ3fEcrL5FxF0Wu+HrMy26w= github.com/pingcap/kvproto v0.0.0-20191213111810-93cb7c623c8b/go.mod h1:WWLmULLO7l8IOcQG+t+ItJ3fEcrL5FxF0Wu+HrMy26w= +github.com/pingcap/kvproto v0.0.0-20200108025604-a4dc183d2af5 h1:RUxQExD5yubAjWGnw8kcxfO9abbiVHIE1rbuCyQCWDE= +github.com/pingcap/kvproto v0.0.0-20200108025604-a4dc183d2af5/go.mod h1:WWLmULLO7l8IOcQG+t+ItJ3fEcrL5FxF0Wu+HrMy26w= github.com/pingcap/kvproto v0.0.0-20200210234432-a965739f8162 h1:lsoIoCoXMpcHvW6jHcqP/prA4I6duAp1DVyG2ULz4bM= github.com/pingcap/kvproto v0.0.0-20200210234432-a965739f8162/go.mod h1:IOdRDPLyda8GX2hE/jO7gqaCV/PNFh8BZQCQZXfIOqI= github.com/pingcap/log v0.0.0-20191012051959-b742a5d432e9 h1:AJD9pZYm72vMgPcQDww9rkZ1DnWfl0pXV3BOWlkYIjA= @@ -345,6 +347,8 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190909003024-a7b16738d86b h1:XfVGCX+0T4WOStkaOsJRllbsiImhB2jgVBGc9L0lPGc= +golang.org/x/net v0.0.0-20190909003024-a7b16738d86b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191002035440-2ec189313ef0 h1:2mqDk8w/o6UmeUCu5Qiq2y7iMf6anbx+YA8d1JFoFrs= golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -392,6 +396,8 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20181004005441-af9cb2a35e7f/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190905072037-92dd089d5514 h1:oFSK4421fpCKRrpzIpybyBVWyht05NegY9+L/3TLAZs= +google.golang.org/genproto v0.0.0-20190905072037-92dd089d5514/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c h1:hrpEMCZ2O7DR5gC1n2AJGVhrwiEjOi35+jxtIuZpTMo= google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/grpc v0.0.0-20180607172857-7a6a684ca69e/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= @@ -421,7 +427,6 @@ gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bl gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3 h1:fvjTMHxHEw/mxHbtzPi3JCcKXQRAnQTBRo6YCJSVHKI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= From 3e82e28c4ce00faaa712a6e7b6c3085181f829b6 Mon Sep 17 00:00:00 2001 From: qupeng Date: Fri, 14 Feb 2020 14:30:05 +0800 Subject: [PATCH 5/5] fix default value about read type Signed-off-by: qupeng --- kv/kv.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kv/kv.go b/kv/kv.go index 83cc44d79240f..374e8e3df07a9 100644 --- a/kv/kv.go +++ b/kv/kv.go @@ -99,7 +99,8 @@ const ( // IsFollowerRead checks if leader is going to be used to read data. func (r ReplicaReadType) IsFollowerRead() bool { - return r != ReplicaReadLeader + // In some cases the default value is 0, which should be treated as `ReplicaReadLeader`. + return r != ReplicaReadLeader && r != 0 } // Those limits is enforced to make sure the transaction can be well handled by TiKV.