diff --git a/src/main/java/org/tikv/common/operation/iterator/ConcreteScanIterator.java b/src/main/java/org/tikv/common/operation/iterator/ConcreteScanIterator.java index 8d1659b1d6d..72422736e76 100644 --- a/src/main/java/org/tikv/common/operation/iterator/ConcreteScanIterator.java +++ b/src/main/java/org/tikv/common/operation/iterator/ConcreteScanIterator.java @@ -75,9 +75,13 @@ TiRegion loadCurrentRegionToCache() throws GrpcException { TiRegion region; try (RegionStoreClient client = builder.build(startKey)) { client.setTimeout(conf.getScanTimeout()); - region = client.getRegion(); BackOffer backOffer = ConcreteBackOffer.newScannerNextMaxBackOff(); currentCache = client.scan(backOffer, startKey, version); + // If we get region before scan, we will use region from cache which + // may have wrong end key. This may miss some regions that split from old region. + // Client will get the newest region during scan. So we need to + // update region after scan. + region = client.getRegion(); return region; } } diff --git a/src/main/java/org/tikv/common/operation/iterator/RawScanIterator.java b/src/main/java/org/tikv/common/operation/iterator/RawScanIterator.java index 5b27132699d..08a64aaf87f 100644 --- a/src/main/java/org/tikv/common/operation/iterator/RawScanIterator.java +++ b/src/main/java/org/tikv/common/operation/iterator/RawScanIterator.java @@ -57,6 +57,9 @@ TiRegion loadCurrentRegionToCache() throws GrpcException { } else { try { currentCache = client.rawScan(backOffer, startKey, limit, keyOnly); + // Client will get the newest region during scan. So we need to + // update region after scan. + region = client.getRegion(); } catch (final TiKVException e) { backOffer.doBackOff(BackOffFunction.BackOffFuncType.BoRegionMiss, e); continue; diff --git a/src/main/java/org/tikv/common/operation/iterator/ScanIterator.java b/src/main/java/org/tikv/common/operation/iterator/ScanIterator.java index dcce68e147d..69fd0217fd5 100644 --- a/src/main/java/org/tikv/common/operation/iterator/ScanIterator.java +++ b/src/main/java/org/tikv/common/operation/iterator/ScanIterator.java @@ -65,6 +65,7 @@ public abstract class ScanIterator implements Iterator { * * @return TiRegion of current data loaded to cache * @throws GrpcException if scan still fails after backoff + *

TODO : Add test to check it correctness */ abstract TiRegion loadCurrentRegionToCache() throws GrpcException; diff --git a/src/main/java/org/tikv/common/region/RegionStoreClient.java b/src/main/java/org/tikv/common/region/RegionStoreClient.java index 42576fa7ea7..ccc820891f1 100644 --- a/src/main/java/org/tikv/common/region/RegionStoreClient.java +++ b/src/main/java/org/tikv/common/region/RegionStoreClient.java @@ -339,9 +339,6 @@ public List scan( BackOffer backOffer, ByteString startKey, long version, boolean keyOnly) { boolean forWrite = false; while (true) { - // we should refresh region - region = regionManager.getRegionByKey(startKey, backOffer); - Supplier request = () -> ScanRequest.newBuilder() @@ -365,6 +362,10 @@ public List scan( version, forWrite); ScanResponse resp = callWithRetry(backOffer, TikvGrpc.getKvScanMethod(), request, handler); + // retry may refresh region info + // we need to update region after retry + region = regionManager.getRegionByKey(startKey, backOffer); + if (isScanSuccess(backOffer, resp)) { return doScan(resp); } @@ -1253,6 +1254,9 @@ public List rawScan(BackOffer backOffer, ByteString key, int limit, bool regionManager, this, resp -> resp.hasRegionError() ? resp.getRegionError() : null); RawScanResponse resp = callWithRetry(backOffer, TikvGrpc.getRawScanMethod(), factory, handler); + // RegionErrorHandler may refresh region cache due to outdated region info, + // This region need to get newest info from cache. + region = regionManager.getRegionByKey(key, backOffer); return rawScanHelper(resp); } finally { requestTimer.observeDuration();