Repository: tikv/client-go
Pull request #1602 (2025-02-28 09:15:49)

remove useless metric tidb_tikvclient_cop_duration_seconds_bucket
Ref https://github.com/pingcap/tidb/pull/59845

ti-chi-bot[bot]: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by:
**Once this PR has been reviewed and has the lgtm label**, please assign [disksing](https://github.com/disksing) for approval. For more information see [the Code Review Process](https://book.prow.tidb.net/#/workflows/pr).

The full list of commands accepted by this bot can be found [here](https://prow.tidb.net/command-help?repo=tikv%2Fclient-go).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/tikv/client-go/blob/master/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["disksing"]} -->
ti-chi-bot[bot]: Welcome @XuHuaiyu! <br><br>It looks like this is your first PR to <a href='https://github.com/tikv/client-go'>tikv/client-go</a> 🎉. <br><br>I'm the bot to help you request reviewers, add labels and more, See [available commands](https://prow.tidb.net/command-help). <br><br>We want to make sure your contribution gets all the attention it needs! <br><br> <br><br>Thank you, and welcome to tikv/client-go. :smiley:
ti-chi-bot[bot]: Thanks for your pull request. Before we can look at it, you'll need to add a 'DCO signoff' to your commits.

:memo: **Please follow instructions in the [contributing guide](https://github.com/tikv/client-go/blob/master/CONTRIBUTING.md) to update your commits with the DCO**

Full details of the Developer Certificate of Origin can be found at [developercertificate.org](https://developercertificate.org/).

**The list of commits missing DCO signoff**:

- [be2631c](https://github.com/tikv/client-go/commits/be2631c95be6f4e9c10b0b2bdf5d5aefc19d90d5) remove useless metric tidb_tikvclient_cop_duration_seconds_bucket

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>


Patch:
diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml
index d675928..1fa96a3 100644
--- a/.github/workflows/integration.yml
+++ b/.github/workflows/integration.yml
@@ -2,13 +2,13 @@ name: Integration Test
 
 on:
   push:
-    branches: [ master ]
+    branches: [master]
   pull_request:
-    branches: [ master ]
+    branches: [master]
 
 jobs:
-
   integration-local:
+    if: ${{ !contains(github.event.pull_request.labels.*.name, 'skip-integration-tests') }}
     runs-on: ubuntu-latest
     steps:
       - name: Checkout
@@ -24,6 +24,7 @@ jobs:
         working-directory: integration_tests
 
   integration-local-race:
+    if: ${{ !contains(github.event.pull_request.labels.*.name, 'skip-integration-tests') }}
     runs-on: ubuntu-latest
     steps:
       - name: Checkout
@@ -39,6 +40,7 @@ jobs:
         working-directory: integration_tests
 
   integration-tikv:
+    if: ${{ !contains(github.event.pull_request.labels.*.name, 'skip-integration-tests') }}
     runs-on: ubuntu-latest
     steps:
       - name: Checkout
@@ -78,6 +80,7 @@ jobs:
         working-directory: integration_tests
 
   integration-raw-tikv:
+    if: ${{ !contains(github.event.pull_request.labels.*.name, 'skip-integration-tests') }}
     runs-on: ubuntu-latest
     strategy:
       matrix:
diff --git a/examples/gcworker/go.mod b/examples/gcworker/go.mod
index 5e675bd..83cdd38 100644
--- a/examples/gcworker/go.mod
+++ b/examples/gcworker/go.mod
@@ -23,7 +23,7 @@ require (
 	github.com/opentracing/opentracing-go v1.2.0 // indirect
 	github.com/pingcap/errors v0.11.5-0.20211224045212-9687c2b0f87c // indirect
 	github.com/pingcap/failpoint v0.0.0-20240528011301-b51a646c7c86 // indirect
-	github.com/pingcap/kvproto v0.0.0-20250117122752-2b87602a94a1 // indirect
+	github.com/pingcap/kvproto v0.0.0-20250224053625-b6a98c6bf02d // indirect
 	github.com/pingcap/log v1.1.1-0.20221110025148-ca232912c9f3 // indirect
 	github.com/pkg/errors v0.9.1 // indirect
 	github.com/prometheus/client_golang v1.20.5 // indirect
@@ -32,7 +32,7 @@ require (
 	github.com/prometheus/procfs v0.15.1 // indirect
 	github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
 	github.com/tiancaiamao/gp v0.0.0-20221230034425-4025bc8a4d4a // indirect
-	github.com/tikv/pd/client v0.0.0-20250213082949-e8930327be42 // indirect
+	github.com/tikv/pd/client v0.0.0-20250318085533-e8050f72d00d // indirect
 	github.com/twmb/murmur3 v1.1.3 // indirect
 	go.etcd.io/etcd/api/v3 v3.5.10 // indirect
 	go.etcd.io/etcd/client/pkg/v3 v3.5.10 // indirect
diff --git a/examples/rawkv/go.mod b/examples/rawkv/go.mod
index 83fe302..88786a2 100644
--- a/examples/rawkv/go.mod
+++ b/examples/rawkv/go.mod
@@ -23,7 +23,7 @@ require (
 	github.com/opentracing/opentracing-go v1.2.0 // indirect
 	github.com/pingcap/errors v0.11.5-0.20211224045212-9687c2b0f87c // indirect
 	github.com/pingcap/failpoint v0.0.0-20240528011301-b51a646c7c86 // indirect
-	github.com/pingcap/kvproto v0.0.0-20250117122752-2b87602a94a1 // indirect
+	github.com/pingcap/kvproto v0.0.0-20250224053625-b6a98c6bf02d // indirect
 	github.com/pingcap/log v1.1.1-0.20221110025148-ca232912c9f3 // indirect
 	github.com/pkg/errors v0.9.1 // indirect
 	github.com/prometheus/client_golang v1.20.5 // indirect
@@ -32,7 +32,7 @@ require (
 	github.com/prometheus/procfs v0.15.1 // indirect
 	github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
 	github.com/tiancaiamao/gp v0.0.0-20221230034425-4025bc8a4d4a // indirect
-	github.com/tikv/pd/client v0.0.0-20250213082949-e8930327be42 // indirect
+	github.com/tikv/pd/client v0.0.0-20250318085533-e8050f72d00d // indirect
 	github.com/twmb/murmur3 v1.1.3 // indirect
 	go.etcd.io/etcd/api/v3 v3.5.10 // indirect
 	go.etcd.io/etcd/client/pkg/v3 v3.5.10 // indirect
diff --git a/examples/txnkv/1pc_txn/go.mod b/examples/txnkv/1pc_txn/go.mod
index 17e0129..f931632 100644
--- a/examples/txnkv/1pc_txn/go.mod
+++ b/examples/txnkv/1pc_txn/go.mod
@@ -23,7 +23,7 @@ require (
 	github.com/opentracing/opentracing-go v1.2.0 // indirect
 	github.com/pingcap/errors v0.11.5-0.20211224045212-9687c2b0f87c // indirect
 	github.com/pingcap/failpoint v0.0.0-20240528011301-b51a646c7c86 // indirect
-	github.com/pingcap/kvproto v0.0.0-20250117122752-2b87602a94a1 // indirect
+	github.com/pingcap/kvproto v0.0.0-20250224053625-b6a98c6bf02d // indirect
 	github.com/pingcap/log v1.1.1-0.20221110025148-ca232912c9f3 // indirect
 	github.com/pkg/errors v0.9.1 // indirect
 	github.com/prometheus/client_golang v1.20.5 // indirect
@@ -32,7 +32,7 @@ require (
 	github.com/prometheus/procfs v0.15.1 // indirect
 	github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
 	github.com/tiancaiamao/gp v0.0.0-20221230034425-4025bc8a4d4a // indirect
-	github.com/tikv/pd/client v0.0.0-20250213082949-e8930327be42 // indirect
+	github.com/tikv/pd/client v0.0.0-20250318085533-e8050f72d00d // indirect
 	github.com/twmb/murmur3 v1.1.3 // indirect
 	go.etcd.io/etcd/api/v3 v3.5.10 // indirect
 	go.etcd.io/etcd/client/pkg/v3 v3.5.10 // indirect
diff --git a/examples/txnkv/async_commit/go.mod b/examples/txnkv/async_commit/go.mod
index 2b53c80..e9d4a36 100644
--- a/examples/txnkv/async_commit/go.mod
+++ b/examples/txnkv/async_commit/go.mod
@@ -23,7 +23,7 @@ require (
 	github.com/opentracing/opentracing-go v1.2.0 // indirect
 	github.com/pingcap/errors v0.11.5-0.20211224045212-9687c2b0f87c // indirect
 	github.com/pingcap/failpoint v0.0.0-20240528011301-b51a646c7c86 // indirect
-	github.com/pingcap/kvproto v0.0.0-20250117122752-2b87602a94a1 // indirect
+	github.com/pingcap/kvproto v0.0.0-20250224053625-b6a98c6bf02d // indirect
 	github.com/pingcap/log v1.1.1-0.20221110025148-ca232912c9f3 // indirect
 	github.com/pkg/errors v0.9.1 // indirect
 	github.com/prometheus/client_golang v1.20.5 // indirect
@@ -32,7 +32,7 @@ require (
 	github.com/prometheus/procfs v0.15.1 // indirect
 	github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
 	github.com/tiancaiamao/gp v0.0.0-20221230034425-4025bc8a4d4a // indirect
-	github.com/tikv/pd/client v0.0.0-20250213082949-e8930327be42 // indirect
+	github.com/tikv/pd/client v0.0.0-20250318085533-e8050f72d00d // indirect
 	github.com/twmb/murmur3 v1.1.3 // indirect
 	go.etcd.io/etcd/api/v3 v3.5.10 // indirect
 	go.etcd.io/etcd/client/pkg/v3 v3.5.10 // indirect
diff --git a/examples/txnkv/delete_range/go.mod b/examples/txnkv/delete_range/go.mod
index 246fd19..262fa67 100644
--- a/examples/txnkv/delete_range/go.mod
+++ b/examples/txnkv/delete_range/go.mod
@@ -23,7 +23,7 @@ require (
 	github.com/opentracing/opentracing-go v1.2.0 // indirect
 	github.com/pingcap/errors v0.11.5-0.20211224045212-9687c2b0f87c // indirect
 	github.com/pingcap/failpoint v0.0.0-20240528011301-b51a646c7c86 // indirect
-	github.com/pingcap/kvproto v0.0.0-20250117122752-2b87602a94a1 // indirect
+	github.com/pingcap/kvproto v0.0.0-20250224053625-b6a98c6bf02d // indirect
 	github.com/pingcap/log v1.1.1-0.20221110025148-ca232912c9f3 // indirect
 	github.com/pkg/errors v0.9.1 // indirect
 	github.com/prometheus/client_golang v1.20.5 // indirect
@@ -32,7 +32,7 @@ require (
 	github.com/prometheus/procfs v0.15.1 // indirect
 	github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
 	github.com/tiancaiamao/gp v0.0.0-20221230034425-4025bc8a4d4a // indirect
-	github.com/tikv/pd/client v0.0.0-20250213082949-e8930327be42 // indirect
+	github.com/tikv/pd/client v0.0.0-20250318085533-e8050f72d00d // indirect
 	github.com/twmb/murmur3 v1.1.3 // indirect
 	go.etcd.io/etcd/api/v3 v3.5.10 // indirect
 	go.etcd.io/etcd/client/pkg/v3 v3.5.10 // indirect
diff --git a/examples/txnkv/go.mod b/examples/txnkv/go.mod
index 3db30c1..8545b99 100644
--- a/examples/txnkv/go.mod
+++ b/examples/txnkv/go.mod
@@ -23,7 +23,7 @@ require (
 	github.com/opentracing/opentracing-go v1.2.0 // indirect
 	github.com/pingcap/errors v0.11.5-0.20211224045212-9687c2b0f87c // indirect
 	github.com/pingcap/failpoint v0.0.0-20240528011301-b51a646c7c86 // indirect
-	github.com/pingcap/kvproto v0.0.0-20250117122752-2b87602a94a1 // indirect
+	github.com/pingcap/kvproto v0.0.0-20250224053625-b6a98c6bf02d // indirect
 	github.com/pingcap/log v1.1.1-0.20221110025148-ca232912c9f3 // indirect
 	github.com/pkg/errors v0.9.1 // indirect
 	github.com/prometheus/client_golang v1.20.5 // indirect
@@ -32,7 +32,7 @@ require (
 	github.com/prometheus/procfs v0.15.1 // indirect
 	github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
 	github.com/tiancaiamao/gp v0.0.0-20221230034425-4025bc8a4d4a // indirect
-	github.com/tikv/pd/client v0.0.0-20250213082949-e8930327be42 // indirect
+	github.com/tikv/pd/client v0.0.0-20250318085533-e8050f72d00d // indirect
 	github.com/twmb/murmur3 v1.1.3 // indirect
 	go.etcd.io/etcd/api/v3 v3.5.10 // indirect
 	go.etcd.io/etcd/client/pkg/v3 v3.5.10 // indirect
diff --git a/examples/txnkv/pessimistic_txn/go.mod b/examples/txnkv/pessimistic_txn/go.mod
index d97309c..3a519d4 100644
--- a/examples/txnkv/pessimistic_txn/go.mod
+++ b/examples/txnkv/pessimistic_txn/go.mod
@@ -23,7 +23,7 @@ require (
 	github.com/opentracing/opentracing-go v1.2.0 // indirect
 	github.com/pingcap/errors v0.11.5-0.20211224045212-9687c2b0f87c // indirect
 	github.com/pingcap/failpoint v0.0.0-20240528011301-b51a646c7c86 // indirect
-	github.com/pingcap/kvproto v0.0.0-20250117122752-2b87602a94a1 // indirect
+	github.com/pingcap/kvproto v0.0.0-20250224053625-b6a98c6bf02d // indirect
 	github.com/pingcap/log v1.1.1-0.20221110025148-ca232912c9f3 // indirect
 	github.com/pkg/errors v0.9.1 // indirect
 	github.com/prometheus/client_golang v1.20.5 // indirect
@@ -32,7 +32,7 @@ require (
 	github.com/prometheus/procfs v0.15.1 // indirect
 	github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
 	github.com/tiancaiamao/gp v0.0.0-20221230034425-4025bc8a4d4a // indirect
-	github.com/tikv/pd/client v0.0.0-20250213082949-e8930327be42 // indirect
+	github.com/tikv/pd/client v0.0.0-20250318085533-e8050f72d00d // indirect
 	github.com/twmb/murmur3 v1.1.3 // indirect
 	go.etcd.io/etcd/api/v3 v3.5.10 // indirect
 	go.etcd.io/etcd/client/pkg/v3 v3.5.10 // indirect
diff --git a/examples/txnkv/unsafedestoryrange/go.mod b/examples/txnkv/unsafedestoryrange/go.mod
index 4ba2252..ca447fc 100644
--- a/examples/txnkv/unsafedestoryrange/go.mod
+++ b/examples/txnkv/unsafedestoryrange/go.mod
@@ -23,7 +23,7 @@ require (
 	github.com/opentracing/opentracing-go v1.2.0 // indirect
 	github.com/pingcap/errors v0.11.5-0.20211224045212-9687c2b0f87c // indirect
 	github.com/pingcap/failpoint v0.0.0-20240528011301-b51a646c7c86 // indirect
-	github.com/pingcap/kvproto v0.0.0-20250117122752-2b87602a94a1 // indirect
+	github.com/pingcap/kvproto v0.0.0-20250224053625-b6a98c6bf02d // indirect
 	github.com/pingcap/log v1.1.1-0.20221110025148-ca232912c9f3 // indirect
 	github.com/pkg/errors v0.9.1 // indirect
 	github.com/prometheus/client_golang v1.20.5 // indirect
@@ -32,7 +32,7 @@ require (
 	github.com/prometheus/procfs v0.15.1 // indirect
 	github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
 	github.com/tiancaiamao/gp v0.0.0-20221230034425-4025bc8a4d4a // indirect
-	github.com/tikv/pd/client v0.0.0-20250213082949-e8930327be42 // indirect
+	github.com/tikv/pd/client v0.0.0-20250318085533-e8050f72d00d // indirect
 	github.com/twmb/murmur3 v1.1.3 // indirect
 	go.etcd.io/etcd/api/v3 v3.5.10 // indirect
 	go.etcd.io/etcd/client/pkg/v3 v3.5.10 // indirect
diff --git a/go.mod b/go.mod
index d13a2a8..2aaddcb 100644
--- a/go.mod
+++ b/go.mod
@@ -16,14 +16,14 @@ require (
 	github.com/pingcap/errors v0.11.5-0.20211224045212-9687c2b0f87c
 	github.com/pingcap/failpoint v0.0.0-20240528011301-b51a646c7c86
 	github.com/pingcap/goleveldb v0.0.0-20191226122134-f82aafb29989
-	github.com/pingcap/kvproto v0.0.0-20250117122752-2b87602a94a1
+	github.com/pingcap/kvproto v0.0.0-20250224053625-b6a98c6bf02d
 	github.com/pingcap/log v1.1.1-0.20221110025148-ca232912c9f3
 	github.com/pkg/errors v0.9.1
 	github.com/prometheus/client_golang v1.20.5
 	github.com/prometheus/client_model v0.6.1
 	github.com/stretchr/testify v1.9.0
 	github.com/tiancaiamao/gp v0.0.0-20221230034425-4025bc8a4d4a
-	github.com/tikv/pd/client v0.0.0-20250213082949-e8930327be42
+	github.com/tikv/pd/client v0.0.0-20250318085533-e8050f72d00d
 	github.com/twmb/murmur3 v1.1.3
 	go.etcd.io/etcd/api/v3 v3.5.10
 	go.etcd.io/etcd/client/v3 v3.5.10
@@ -50,7 +50,6 @@ require (
 	github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
 	go.etcd.io/etcd/client/pkg/v3 v3.5.10 // indirect
 	go.uber.org/multierr v1.11.0 // indirect
-	golang.org/x/exp v0.0.0-20230711005742-c3f37128e5a4 // indirect
 	golang.org/x/net v0.33.0 // indirect
 	golang.org/x/sys v0.28.0 // indirect
 	golang.org/x/text v0.21.0 // indirect
diff --git a/go.sum b/go.sum
index e7d5f9a..115455f 100644
--- a/go.sum
+++ b/go.sum
@@ -79,8 +79,8 @@ github.com/pingcap/failpoint v0.0.0-20240528011301-b51a646c7c86 h1:tdMsjOqUR7YXH
 github.com/pingcap/failpoint v0.0.0-20240528011301-b51a646c7c86/go.mod h1:exzhVYca3WRtd6gclGNErRWb1qEgff3LYta0LvRmON4=
 github.com/pingcap/goleveldb v0.0.0-20191226122134-f82aafb29989 h1:surzm05a8C9dN8dIUmo4Be2+pMRb6f55i+UIYrluu2E=
 github.com/pingcap/goleveldb v0.0.0-20191226122134-f82aafb29989/go.mod h1:O17XtbryoCJhkKGbT62+L2OlrniwqiGLSqrmdHCMzZw=
-github.com/pingcap/kvproto v0.0.0-20250117122752-2b87602a94a1 h1:rTAyiswGyWSGHJVa4Mkhdi8YfGqfA4LrUVKsH9nrJ8E=
-github.com/pingcap/kvproto v0.0.0-20250117122752-2b87602a94a1/go.mod h1:rXxWk2UnwfUhLXha1jxRWPADw9eMZGWEWCg92Tgmb/8=
+github.com/pingcap/kvproto v0.0.0-20250224053625-b6a98c6bf02d h1:52qhTQG8G8V/pHo/w7F4d2Tw98KMk2C+gAe3U8SWRAg=
+github.com/pingcap/kvproto v0.0.0-20250224053625-b6a98c6bf02d/go.mod h1:rXxWk2UnwfUhLXha1jxRWPADw9eMZGWEWCg92Tgmb/8=
 github.com/pingcap/log v1.1.1-0.20221110025148-ca232912c9f3 h1:HR/ylkkLmGdSSDaD8IDP+SZrdhV1Kibl9KrHxJ9eciw=
 github.com/pingcap/log v1.1.1-0.20221110025148-ca232912c9f3/go.mod h1:DWQW5jICDR7UJh4HtxXSM20Churx4CQL0fwL/SoOSA4=
 github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -113,8 +113,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT
 github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
 github.com/tiancaiamao/gp v0.0.0-20221230034425-4025bc8a4d4a h1:J/YdBZ46WKpXsxsW93SG+q0F8KI+yFrcIDT4c/RNoc4=
 github.com/tiancaiamao/gp v0.0.0-20221230034425-4025bc8a4d4a/go.mod h1:h4xBhSNtOeEosLJ4P7JyKXX7Cabg7AVkWCK5gV2vOrM=
-github.com/tikv/pd/client v0.0.0-20250213082949-e8930327be42 h1:hvB0tf4u5ZU1vAew3MmbyxdYuogDLjIZYzSFt1ACFqo=
-github.com/tikv/pd/client v0.0.0-20250213082949-e8930327be42/go.mod h1:veL5JbFL99G5cvS/Q2cLiFQklIiSrVgsBCwFnXc+Zgo=
+github.com/tikv/pd/client v0.0.0-20250318085533-e8050f72d00d h1:2D+HY8hUlNz+GESWS4IwTBiZVbprvm4TSx3AbFJ46MM=
+github.com/tikv/pd/client v0.0.0-20250318085533-e8050f72d00d/go.mod h1:6fHHp8ecZIIkGyjxKn/oZFqX5dzrRkcHjFJPlBpigzQ=
 github.com/twmb/murmur3 v1.1.3 h1:D83U0XYKcHRYwYIpBKf3Pks91Z0Byda/9SJ8B6EMRcA=
 github.com/twmb/murmur3 v1.1.3/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ=
 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -147,8 +147,6 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
-golang.org/x/exp v0.0.0-20230711005742-c3f37128e5a4 h1:QLureRX3moex6NVu/Lr4MGakp9FdA7sBHGBmvRW7NaM=
-golang.org/x/exp v0.0.0-20230711005742-c3f37128e5a4/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
 golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
diff --git a/internal/locate/pd_codec.go b/internal/locate/pd_codec.go
index 6041ad5..15008be 100644
--- a/internal/locate/pd_codec.go
+++ b/internal/locate/pd_codec.go
@@ -44,10 +44,13 @@ import (
 	pd "github.com/tikv/pd/client"
 	"github.com/tikv/pd/client/clients/router"
 	"github.com/tikv/pd/client/opt"
+	"github.com/tikv/pd/client/pkg/caller"
 )
 
 var _ pd.Client = &CodecPDClient{}
 
+const componentName = "codec-pd-client"
+
 // CodecPDClient wraps a PD Client to decode the encoded keys in region meta.
 type CodecPDClient struct {
 	pd.Client
@@ -57,7 +60,7 @@ type CodecPDClient struct {
 // NewCodecPDClient creates a CodecPDClient in API v1.
 func NewCodecPDClient(mode apicodec.Mode, client pd.Client) *CodecPDClient {
 	codec := apicodec.NewCodecV1(mode)
-	return &CodecPDClient{client, codec}
+	return &CodecPDClient{client.WithCallerComponent(componentName), codec}
 }
 
 // NewCodecPDClientWithKeyspace creates a CodecPDClient in API v2 with keyspace name.
@@ -71,7 +74,7 @@ func NewCodecPDClientWithKeyspace(mode apicodec.Mode, client pd.Client, keyspace
 		return nil, err
 	}
 
-	return &CodecPDClient{client, codec}, nil
+	return &CodecPDClient{client.WithCallerComponent(componentName), codec}, nil
 }
 
 // GetKeyspaceID attempts to retrieve keyspace ID corresponding to the given keyspace name from PD.
@@ -202,3 +205,8 @@ func (c *CodecPDClient) decodeRegionKeyInPlace(r *router.Region) error {
 	}
 	return err
 }
+
+// WithCallerComponent returns a new PD client with the specified caller component.
+func (c *CodecPDClient) WithCallerComponent(component caller.Component) pd.Client {
+	return &CodecPDClient{c.Client.WithCallerComponent(component), c.codec}
+}
diff --git a/internal/locate/region_cache.go b/internal/locate/region_cache.go
index 8164d36..d6887f0 100644
--- a/internal/locate/region_cache.go
+++ b/internal/locate/region_cache.go
@@ -687,7 +687,7 @@ func NewRegionCache(pdClient pd.Client, opt ...RegionCacheOpt) *RegionCache {
 	}
 
 	c := &RegionCache{
-		pdClient:                      pdClient,
+		pdClient:                      pdClient.WithCallerComponent("region-cache"),
 		requestHealthFeedbackCallback: options.requestHealthFeedbackCallback,
 	}
 
diff --git a/internal/locate/region_request.go b/internal/locate/region_request.go
index b6b215a..2300cb6 100644
--- a/internal/locate/region_request.go
+++ b/internal/locate/region_request.go
@@ -873,15 +873,14 @@ func (s *sendReqState) next(
 		defer s.releaseStoreToken(s.vars.rpcCtx.Store)
 	}
 
-	sendCtx := s.send(bo, req, timeout)
+	canceled := s.send(bo, req, timeout)
 	s.vars.sendTimes++
 
 	if s.vars.err != nil {
 		// Because in rpc logic, context.Cancel() will be transferred to rpcContext.Cancel error. For rpcContext cancel,
 		// we need to retry the request. But for context cancel active, for example, limitExec gets the required rows,
 		// we shouldn't retry the request, it will go to backoff and hang in retry logic.
-		if sendCtx.Err() != nil && errors.Cause(sendCtx.Err()) == context.Canceled {
-			metrics.TiKVRPCErrorCounter.WithLabelValues("context-canceled", storeIDLabel(s.vars.rpcCtx)).Inc()
+		if canceled {
 			return true
 		}
 		if val, e := util.EvalFailpoint("noRetryOnRpcError"); e == nil && val.(bool) {
@@ -912,9 +911,9 @@ func (s *sendReqState) next(
 	return true
 }
 
-func (s *sendReqState) send(bo *retry.Backoffer, req *tikvrpc.Request, timeout time.Duration) (ctx context.Context) {
+func (s *sendReqState) send(bo *retry.Backoffer, req *tikvrpc.Request, timeout time.Duration) (canceled bool) {
 	rpcCtx := s.vars.rpcCtx
-	ctx = bo.GetCtx()
+	ctx := bo.GetCtx()
 	if rawHook := ctx.Value(RPCCancellerCtxKey{}); rawHook != nil {
 		var cancel context.CancelFunc
 		ctx, cancel = rawHook.(*RPCCanceller).WithCancel(ctx)
@@ -1057,6 +1056,9 @@ func (s *sendReqState) send(bo *retry.Backoffer, req *tikvrpc.Request, timeout t
 			s.Stats.RecordRPCErrorStats(errStr)
 			s.recordRPCAccessInfo(req, s.vars.rpcCtx, errStr)
 		}
+		if canceled = ctx.Err() != nil && errors.Cause(ctx.Err()) == context.Canceled; canceled {
+			metrics.TiKVRPCErrorCounter.WithLabelValues("context-canceled", storeIDLabel(s.vars.rpcCtx)).Inc()
+		}
 	}
 	return
 }
diff --git a/internal/locate/store_cache.go b/internal/locate/store_cache.go
index 7d4583f..b604814 100644
--- a/internal/locate/store_cache.go
+++ b/internal/locate/store_cache.go
@@ -71,7 +71,7 @@ type storeCache interface {
 }
 
 func newStoreCache(pdClient pd.Client) *storeCacheImpl {
-	c := &storeCacheImpl{pdClient: pdClient}
+	c := &storeCacheImpl{pdClient: pdClient.WithCallerComponent("store-cache")}
 	c.notifyCheckCh = make(chan struct{}, 1)
 	c.storeMu.stores = make(map[uint64]*Store)
 	c.tiflashComputeStoreMu.needReload = true
diff --git a/internal/mockstore/mocktikv/pd.go b/internal/mockstore/mocktikv/pd.go
index f05937e..e48b9a1 100644
--- a/internal/mockstore/mocktikv/pd.go
+++ b/internal/mockstore/mocktikv/pd.go
@@ -382,7 +382,7 @@ func (c *pdClient) SplitAndScatterRegions(ctx context.Context, splitKeys [][]byt
 	return nil, nil
 }
 
-func (c *pdClient) GetAllMembers(ctx context.Context) ([]*pdpb.Member, error) {
+func (c *pdClient) GetAllMembers(ctx context.Context) (*pdpb.GetMembersResponse, error) {
 	return nil, nil
 }
 
diff --git a/metrics/metrics.go b/metrics/metrics.go
index faec575..2f9caa6 100644
--- a/metrics/metrics.go
+++ b/metrics/metrics.go
@@ -46,7 +46,6 @@ var (
 	TiKVSendReqHistogram                           *prometheus.HistogramVec
 	TiKVSendReqSummary                             *prometheus.SummaryVec
 	TiKVRPCNetLatencyHistogram                     *prometheus.HistogramVec
-	TiKVCoprocessorHistogram                       *prometheus.HistogramVec
 	TiKVLockResolverCounter                        *prometheus.CounterVec
 	TiKVRegionErrorCounter                         *prometheus.CounterVec
 	TiKVRPCErrorCounter                            *prometheus.CounterVec
@@ -195,16 +194,6 @@ func initMetrics(namespace, subsystem string, constLabels prometheus.Labels) {
 			ConstLabels: constLabels,
 		}, []string{LblStore, LblScope})
 
-	TiKVCoprocessorHistogram = prometheus.NewHistogramVec(
-		prometheus.HistogramOpts{
-			Namespace:   namespace,
-			Subsystem:   subsystem,
-			Name:        "cop_duration_seconds",
-			Help:        "Run duration of a single coprocessor task, includes backoff time.",
-			Buckets:     prometheus.ExponentialBuckets(0.0005, 2, 29), // 0.5ms ~ 1.5days
-			ConstLabels: constLabels,
-		}, []string{LblStore, LblStaleRead, LblScope})
-
 	TiKVLockResolverCounter = prometheus.NewCounterVec(
 		prometheus.CounterOpts{
 			Namespace:   namespace,
@@ -884,7 +873,6 @@ func RegisterMetrics() {
 	prometheus.MustRegister(TiKVSendReqHistogram)
 	prometheus.MustRegister(TiKVSendReqSummary)
 	prometheus.MustRegister(TiKVRPCNetLatencyHistogram)
-	prometheus.MustRegister(TiKVCoprocessorHistogram)
 	prometheus.MustRegister(TiKVLockResolverCounter)
 	prometheus.MustRegister(TiKVRegionErrorCounter)
 	prometheus.MustRegister(TiKVRPCErrorCounter)
diff --git a/oracle/oracles/local.go b/oracle/oracles/local.go
index a980bbd..e5aa21f 100644
--- a/oracle/oracles/local.go
+++ b/oracle/oracles/local.go
@@ -36,11 +36,9 @@ package oracles
 
 import (
 	"context"
-	"math"
 	"sync"
 	"time"
 
-	"github.com/pingcap/errors"
 	"github.com/tikv/client-go/v2/oracle"
 )
 
@@ -152,22 +150,6 @@ func (l *localOracle) GetExternalTimestamp(ctx context.Context) (uint64, error)
 }
 
 func (l *localOracle) ValidateReadTS(ctx context.Context, readTS uint64, isStaleRead bool, opt *oracle.Option) error {
-	if readTS == math.MaxUint64 {
-		if isStaleRead {
-			return oracle.ErrLatestStaleRead{}
-		}
-		return nil
-	}
-
-	currentTS, err := l.GetTimestamp(ctx, opt)
-	if err != nil {
-		return errors.Errorf("fail to validate read timestamp: %v", err)
-	}
-	if currentTS < readTS {
-		return oracle.ErrFutureTSRead{
-			ReadTS:    readTS,
-			CurrentTS: currentTS,
-		}
-	}
+	// local oracle is not supposed to be used
 	return nil
 }
diff --git a/oracle/oracles/mock.go b/oracle/oracles/mock.go
index 757ce31..5ed8d75 100644
--- a/oracle/oracles/mock.go
+++ b/oracle/oracles/mock.go
@@ -36,7 +36,6 @@ package oracles
 
 import (
 	"context"
-	"math"
 	"sync"
 	"time"
 
@@ -139,23 +138,6 @@ func (o *MockOracle) SetLowResolutionTimestampUpdateInterval(time.Duration) erro
 }
 
 func (o *MockOracle) ValidateReadTS(ctx context.Context, readTS uint64, isStaleRead bool, opt *oracle.Option) error {
-	if readTS == math.MaxUint64 {
-		if isStaleRead {
-			return oracle.ErrLatestStaleRead{}
-		}
-		return nil
-	}
-
-	currentTS, err := o.GetTimestamp(ctx, opt)
-	if err != nil {
-		return errors.Errorf("fail to validate read timestamp: %v", err)
-	}
-	if currentTS < readTS {
-		return oracle.ErrFutureTSRead{
-			ReadTS:    readTS,
-			CurrentTS: currentTS,
-		}
-	}
 	return nil
 }
 
diff --git a/oracle/oracles/pd.go b/oracle/oracles/pd.go
index 60f0ee7..98813ad 100644
--- a/oracle/oracles/pd.go
+++ b/oracle/oracles/pd.go
@@ -47,6 +47,7 @@ import (
 	"github.com/tikv/client-go/v2/internal/logutil"
 	"github.com/tikv/client-go/v2/metrics"
 	"github.com/tikv/client-go/v2/oracle"
+	"github.com/tikv/client-go/v2/util"
 	pd "github.com/tikv/pd/client"
 	"github.com/tikv/pd/client/clients/tso"
 	"go.uber.org/zap"
@@ -179,7 +180,7 @@ func NewPdOracle(pdClient pd.Client, options *PDOracleOptions) (oracle.Oracle, e
 	}
 
 	o := &pdOracle{
-		c:                    pdClient,
+		c:                    pdClient.WithCallerComponent("oracle"),
 		quit:                 make(chan struct{}),
 		lastTSUpdateInterval: atomic.Int64{},
 	}
@@ -647,6 +648,7 @@ func (o *pdOracle) getCurrentTSForValidation(ctx context.Context, opt *oracle.Op
 		// waiting for reusing the same result should not be canceled. So pass context.Background() instead of the
 		// current ctx.
 		res, err := o.GetTimestamp(context.Background(), opt)
+		_, _ = util.EvalFailpoint("getCurrentTSForValidationBeforeReturn")
 		return res, err
 	})
 	select {
@@ -660,7 +662,22 @@ func (o *pdOracle) getCurrentTSForValidation(ctx context.Context, opt *oracle.Op
 	}
 }
 
-func (o *pdOracle) ValidateReadTS(ctx context.Context, readTS uint64, isStaleRead bool, opt *oracle.Option) (errRet error) {
+// ValidateReadTSForTidbSnapshot is a flag in context, indicating whether the read ts is for tidb_snapshot.
+// This is a special approach for release branches to minimize code changes to reduce risks.
+type ValidateReadTSForTidbSnapshot struct{}
+
+func (o *pdOracle) ValidateReadTS(ctx context.Context, readTS uint64, isStaleRead bool, opt *oracle.Option) error {
+	// For a mistake we've seen
+	if readTS >= math.MaxInt64 && readTS < math.MaxUint64 {
+		return errors.Errorf("MaxInt64 <= readTS < MaxUint64, readTS=%v", readTS)
+	}
+
+	// only check stale reads and reads using `tidb_snapshot`
+	forTidbSnapshot := ctx.Value(ValidateReadTSForTidbSnapshot{}) != nil
+	if !forTidbSnapshot && !isStaleRead {
+		return nil
+	}
+
 	if readTS == math.MaxUint64 {
 		if isStaleRead {
 			return oracle.ErrLatestStaleRead{}
@@ -668,34 +685,67 @@ func (o *pdOracle) ValidateReadTS(ctx context.Context, readTS uint64, isStaleRea
 		return nil
 	}
 
-	latestTSInfo, exists := o.getLastTSWithArrivalTS(opt.TxnScope)
-	// If we fail to get latestTSInfo or the readTS exceeds it, get a timestamp from PD to double-check.
-	// But we don't need to strictly fetch the latest TS. So if there are already concurrent calls to this function
-	// loading the latest TS, we can just reuse the same result to avoid too many concurrent GetTS calls.
-	if !exists || readTS > latestTSInfo.tso {
-		currentTS, err := o.getCurrentTSForValidation(ctx, opt)
-		if err != nil {
-			return errors.Errorf("fail to validate read timestamp: %v", err)
-		}
-		if isStaleRead {
-			o.adjustUpdateLowResolutionTSIntervalWithRequestedStaleness(readTS, currentTS, time.Now())
-		}
-		if readTS > currentTS {
-			return oracle.ErrFutureTSRead{
-				ReadTS:    readTS,
-				CurrentTS: currentTS,
+	retrying := false
+	for {
+		latestTSInfo, exists := o.getLastTSWithArrivalTS(opt.TxnScope)
+		// If we fail to get latestTSInfo or the readTS exceeds it, get a timestamp from PD to double-check.
+		// But we don't need to strictly fetch the latest TS. So if there are already concurrent calls to this function
+		// loading the latest TS, we can just reuse the same result to avoid too many concurrent GetTS calls.
+		if !exists || readTS > latestTSInfo.tso {
+			currentTS, err := o.getCurrentTSForValidation(ctx, opt)
+			if err != nil {
+				return errors.Errorf("fail to validate read timestamp: %v", err)
+			}
+			if isStaleRead && !retrying {
+				// Trigger the adjustment at most once in a single invocation.
+				o.adjustUpdateLowResolutionTSIntervalWithRequestedStaleness(readTS, currentTS, time.Now())
+			}
+			if readTS > currentTS {
+				// It's possible that the caller is checking a ts that's legal but not fetched from the current oracle
+				// object. In this case, it's possible that:
+				//   * The ts is not be cached by the low resolution ts (so that readTS > latestTSInfo.TSO);
+				//   * ... and then the getCurrentTSForValidation (which uses a singleflight internally) reuse a
+				//     previously-started call and returns an older ts
+				// so that it may cause the check false-positive.
+				// To handle this case, we do not fail immediately when the check doesn't at once; instead, retry one
+				// more time. In the retry:
+				//   * Considering that there can already be some other concurrent GetTimestamp operation that may have updated
+				//     the low resolution ts, so check it again. If it passes, then no need to get the next ts from PD,
+				//     which is slow.
+				//   * Then, call getCurrentTSForValidation and check again. As the current GetTimestamp operation
+				//     inside getCurrentTSForValidation must be started after finishing the previous one (while the
+				//     latter is finished after starting this invocation to ValidateReadTS), then we can conclude that
+				//     the next ts returned by getCurrentTSForValidation must be greater than any ts allocated by PD
+				//     before the current invocation to ValidateReadTS.
+				skipRetry := false
+				if val, err1 := util.EvalFailpoint("validateReadTSRetryGetTS"); err1 == nil {
+					if str, ok := val.(string); ok {
+						if str == "skip" {
+							skipRetry = true
+						}
+					}
+				}
+				if !retrying && !skipRetry {
+					retrying = true
+					continue
+				}
+				return oracle.ErrFutureTSRead{
+					ReadTS:    readTS,
+					CurrentTS: currentTS,
+				}
+			}
+		} else if !retrying && isStaleRead {
+			// Trigger the adjustment at most once in a single invocation.
+			estimatedCurrentTS, err := o.getStaleTimestampWithLastTS(latestTSInfo, 0)
+			if err != nil {
+				logutil.Logger(ctx).Warn("failed to estimate current ts by getSlateTimestamp for auto-adjusting update low resolution ts interval",
+					zap.Error(err), zap.Uint64("readTS", readTS), zap.String("txnScope", opt.TxnScope))
+			} else {
+				o.adjustUpdateLowResolutionTSIntervalWithRequestedStaleness(readTS, estimatedCurrentTS, time.Now())
 			}
 		}
-	} else if isStaleRead {
-		estimatedCurrentTS, err := o.getStaleTimestampWithLastTS(latestTSInfo, 0)
-		if err != nil {
-			logutil.Logger(ctx).Warn("failed to estimate current ts by getSlateTimestamp for auto-adjusting update low resolution ts interval",
-				zap.Error(err), zap.Uint64("readTS", readTS), zap.String("txnScope", opt.TxnScope))
-		} else {
-			o.adjustUpdateLowResolutionTSIntervalWithRequestedStaleness(readTS, estimatedCurrentTS, time.Now())
-		}
+		return nil
 	}
-	return nil
 }
 
 // adjustUpdateLowResolutionTSIntervalWithRequestedStaleness triggers adjustments the update interval of low resolution
diff --git a/rawkv/rawkv.go b/rawkv/rawkv.go
index da59325..91f4078 100644
--- a/rawkv/rawkv.go
+++ b/rawkv/rawkv.go
@@ -69,6 +69,7 @@ const (
 	rawBatchPutSize = 16 * 1024
 	// rawBatchPairCount is the maximum limit for rawkv each batch get/delete request.
 	rawBatchPairCount = 512
+	componentName     = caller.Component("rawkv-client-go")
 )
 
 type rawOptions struct {
@@ -204,7 +205,7 @@ func NewClientWithOpts(ctx context.Context, pdAddrs []string, opts ...ClientOpt)
 	}
 
 	// Use an unwrapped PDClient to obtain keyspace meta.
-	pdCli, err := pd.NewClientWithContext(ctx, caller.Component("rawkv-client-go"), pdAddrs, pd.SecurityOption{
+	pdCli, err := pd.NewClientWithContext(ctx, componentName, pdAddrs, pd.SecurityOption{
 		CAPath:   opt.security.ClusterSSLCA,
 		CertPath: opt.security.ClusterSSLCert,
 		KeyPath:  opt.security.ClusterSSLKey,
@@ -240,7 +241,7 @@ func NewClientWithOpts(ctx context.Context, pdAddrs []string, opts ...ClientOpt)
 		apiVersion:  opt.apiVersion,
 		clusterID:   pdCli.GetClusterID(ctx),
 		regionCache: locate.NewRegionCache(pdCli),
-		pdClient:    pdCli,
+		pdClient:    pdCli.WithCallerComponent(componentName),
 		rpcClient:   rpcCli,
 	}, nil
 }
diff --git a/tikv/kv.go b/tikv/kv.go
index cd5f17d..275d07a 100644
--- a/tikv/kv.go
+++ b/tikv/kv.go
@@ -285,7 +285,7 @@ func NewKVStore(uuid string, pdClient pd.Client, spkv SafePointKV, tikvclient Cl
 		clusterID:       pdClient.GetClusterID(context.TODO()),
 		uuid:            uuid,
 		oracle:          o,
-		pdClient:        pdClient,
+		pdClient:        pdClient.WithCallerComponent("kv-store"),
 		regionCache:     regionCache,
 		kv:              spkv,
 		safePoint:       0,
@@ -916,7 +916,7 @@ func NewLockResolver(etcdAddrs []string, security config.Security, opts ...opt.C
 	if err != nil {
 		return nil, errors.WithStack(err)
 	}
-	pdCli = util.InterceptedPDClient{Client: pdCli}
+	pdCli = util.NewInterceptedPDClient(pdCli)
 	uuid := fmt.Sprintf("tikv-%v", pdCli.GetClusterID(context.TODO()))
 
 	tlsConfig, err := security.ToTLSConfig()
diff --git a/txnkv/client.go b/txnkv/client.go
index aa37333..bfcaad4 100644
--- a/txnkv/client.go
+++ b/txnkv/client.go
@@ -76,7 +76,7 @@ func NewClient(pdAddrs []string, opts ...ClientOpt) (*Client, error) {
 		return nil, errors.WithStack(err)
 	}
 
-	pdClient = util.InterceptedPDClient{Client: pdClient}
+	pdClient = util.NewInterceptedPDClient(pdClient)
 
 	// Construct codec from options.
 	var codecCli *tikv.CodecPDClient
diff --git a/util/execdetails.go b/util/execdetails.go
index 5977ee9..8838cfe 100644
--- a/util/execdetails.go
+++ b/util/execdetails.go
@@ -544,6 +544,14 @@ type WriteDetail struct {
 	ApplyWriteWalDuration time.Duration
 	// ApplyWriteMemtableNanos is the time spent on writing to the memtable of the KV RocksDB.
 	ApplyWriteMemtableDuration time.Duration
+	// SchedulerLatchWaitDuration is the time spent on waiting for acquiring latch in the scheduler layer.
+	SchedulerLatchWaitDuration time.Duration
+	// SchedulerProcessDuration is the time spent on processing for the write command in the scheduler layer.
+	SchedulerProcessDuration time.Duration
+	// SchedulerThrottleDuration is the time spent on waiting due to throttled in the scheduler layer.
+	SchedulerThrottleDuration time.Duration
+	// SchedulerPessimisticLockWaitDuration is the time spent on waiting for pessimistic locks in the scheduler layer.
+	SchedulerPessimisticLockWaitDuration time.Duration
 }
 
 // MergeFromWriteDetailPb merges WriteDetail protobuf into the current WriteDetail
@@ -562,6 +570,10 @@ func (wd *WriteDetail) MergeFromWriteDetailPb(pb *kvrpcpb.WriteDetail) {
 		wd.ApplyWriteLeaderWaitDuration += time.Duration(pb.ApplyWriteLeaderWaitNanos) * time.Nanosecond
 		wd.ApplyWriteWalDuration += time.Duration(pb.ApplyWriteWalNanos) * time.Nanosecond
 		wd.ApplyWriteMemtableDuration += time.Duration(pb.ApplyWriteMemtableNanos) * time.Nanosecond
+		wd.SchedulerLatchWaitDuration += time.Duration(pb.LatchWaitNanos) * time.Nanosecond
+		wd.SchedulerProcessDuration += time.Duration(pb.ProcessNanos) * time.Nanosecond
+		wd.SchedulerThrottleDuration += time.Duration(pb.ThrottleNanos) * time.Nanosecond
+		wd.SchedulerPessimisticLockWaitDuration += time.Duration(pb.PessimisticLockWaitNanos) * time.Nanosecond
 	}
 }
 
@@ -580,6 +592,10 @@ func (wd *WriteDetail) Merge(writeDetail *WriteDetail) {
 	atomic.AddInt64((*int64)(&wd.ApplyWriteLeaderWaitDuration), int64(writeDetail.ApplyWriteLeaderWaitDuration))
 	atomic.AddInt64((*int64)(&wd.ApplyWriteWalDuration), int64(writeDetail.ApplyWriteWalDuration))
 	atomic.AddInt64((*int64)(&wd.ApplyWriteMemtableDuration), int64(writeDetail.ApplyWriteMemtableDuration))
+	atomic.AddInt64((*int64)(&wd.SchedulerLatchWaitDuration), int64(writeDetail.SchedulerLatchWaitDuration))
+	atomic.AddInt64((*int64)(&wd.SchedulerProcessDuration), int64(writeDetail.SchedulerProcessDuration))
+	atomic.AddInt64((*int64)(&wd.SchedulerThrottleDuration), int64(writeDetail.SchedulerThrottleDuration))
+	atomic.AddInt64((*int64)(&wd.SchedulerPessimisticLockWaitDuration), int64(writeDetail.SchedulerPessimisticLockWaitDuration))
 }
 
 var zeroWriteDetail = WriteDetail{}
@@ -616,6 +632,20 @@ func (wd *WriteDetail) String() string {
 	buf.WriteString(FormatDuration(wd.ApplyWriteWalDuration))
 	buf.WriteString(", write_memtable: ")
 	buf.WriteString(FormatDuration(wd.ApplyWriteMemtableDuration))
+	buf.WriteString("}, scheduler: {process: ")
+	buf.WriteString(FormatDuration(wd.SchedulerProcessDuration))
+	if wd.SchedulerLatchWaitDuration > 0 {
+		buf.WriteString(", latch_wait: ")
+		buf.WriteString(FormatDuration(wd.SchedulerLatchWaitDuration))
+	}
+	if wd.SchedulerPessimisticLockWaitDuration > 0 {
+		buf.WriteString(", pessimistic_lock_wait: ")
+		buf.WriteString(FormatDuration(wd.SchedulerPessimisticLockWaitDuration))
+	}
+	if wd.SchedulerThrottleDuration > 0 {
+		buf.WriteString(", throttle: ")
+		buf.WriteString(FormatDuration(wd.SchedulerThrottleDuration))
+	}
 	buf.WriteString("}}")
 	return buf.String()
 }
diff --git a/util/pd_interceptor.go b/util/pd_interceptor.go
index 41eaa66..614fb27 100644
--- a/util/pd_interceptor.go
+++ b/util/pd_interceptor.go
@@ -44,6 +44,7 @@ import (
 	"github.com/tikv/pd/client/clients/router"
 	"github.com/tikv/pd/client/clients/tso"
 	"github.com/tikv/pd/client/opt"
+	"github.com/tikv/pd/client/pkg/caller"
 )
 
 var (
@@ -64,6 +65,10 @@ type InterceptedPDClient struct {
 	pd.Client
 }
 
+func NewInterceptedPDClient(client pd.Client) *InterceptedPDClient {
+	return &InterceptedPDClient{client.WithCallerComponent("intercepted-pd-client")}
+}
+
 // interceptedTsFuture is a PD's wrapper future to record stmt detail.
 type interceptedTsFuture struct {
 	tso.TSFuture
@@ -137,3 +142,8 @@ func (m InterceptedPDClient) GetStore(ctx context.Context, storeID uint64) (*met
 	recordPDWaitTime(ctx, start)
 	return s, err
 }
+
+// WithCallerComponent implements pd.Client#WithCallerComponent.
+func (m InterceptedPDClient) WithCallerComponent(component caller.Component) pd.Client {
+	return NewInterceptedPDClient(m.Client.WithCallerComponent(component))
+}


Test patch:
diff --git a/integration_tests/go.mod b/integration_tests/go.mod
index 2558f02..dda0dfe 100644
--- a/integration_tests/go.mod
+++ b/integration_tests/go.mod
@@ -6,13 +6,13 @@ require (
 	github.com/ninedraft/israce v0.0.3
 	github.com/pingcap/errors v0.11.5-0.20240318064555-6bd07397691f
 	github.com/pingcap/failpoint v0.0.0-20240528011301-b51a646c7c86
-	github.com/pingcap/kvproto v0.0.0-20250117122752-2b87602a94a1
+	github.com/pingcap/kvproto v0.0.0-20250224053625-b6a98c6bf02d
 	github.com/pingcap/tidb v1.1.0-beta.0.20250208075453-ad2c9f464fde
 	github.com/pkg/errors v0.9.1
 	github.com/stretchr/testify v1.10.0
 	github.com/tidwall/gjson v1.14.1
 	github.com/tikv/client-go/v2 v2.0.8-0.20250207065327-ec9ad0fd70cf
-	github.com/tikv/pd/client v0.0.0-20250213082949-e8930327be42
+	github.com/tikv/pd/client v0.0.0-20250318085533-e8050f72d00d
 	go.uber.org/goleak v1.3.0
 )
 
diff --git a/integration_tests/go.sum b/integration_tests/go.sum
index 479f656..3892ad3 100644
--- a/integration_tests/go.sum
+++ b/integration_tests/go.sum
@@ -1351,8 +1351,8 @@ github.com/pingcap/fn v1.0.0/go.mod h1:u9WZ1ZiOD1RpNhcI42RucFh/lBuzTu6rw88a+oF2Z
 github.com/pingcap/goleveldb v0.0.0-20191226122134-f82aafb29989 h1:surzm05a8C9dN8dIUmo4Be2+pMRb6f55i+UIYrluu2E=
 github.com/pingcap/goleveldb v0.0.0-20191226122134-f82aafb29989/go.mod h1:O17XtbryoCJhkKGbT62+L2OlrniwqiGLSqrmdHCMzZw=
 github.com/pingcap/kvproto v0.0.0-20241113043844-e1fa7ea8c302/go.mod h1:rXxWk2UnwfUhLXha1jxRWPADw9eMZGWEWCg92Tgmb/8=
-github.com/pingcap/kvproto v0.0.0-20250117122752-2b87602a94a1 h1:rTAyiswGyWSGHJVa4Mkhdi8YfGqfA4LrUVKsH9nrJ8E=
-github.com/pingcap/kvproto v0.0.0-20250117122752-2b87602a94a1/go.mod h1:rXxWk2UnwfUhLXha1jxRWPADw9eMZGWEWCg92Tgmb/8=
+github.com/pingcap/kvproto v0.0.0-20250224053625-b6a98c6bf02d h1:52qhTQG8G8V/pHo/w7F4d2Tw98KMk2C+gAe3U8SWRAg=
+github.com/pingcap/kvproto v0.0.0-20250224053625-b6a98c6bf02d/go.mod h1:rXxWk2UnwfUhLXha1jxRWPADw9eMZGWEWCg92Tgmb/8=
 github.com/pingcap/log v0.0.0-20210625125904-98ed8e2eb1c7/go.mod h1:8AanEdAHATuRurdGxZXBz0At+9avep+ub7U1AGYLIMM=
 github.com/pingcap/log v1.1.0/go.mod h1:DWQW5jICDR7UJh4HtxXSM20Churx4CQL0fwL/SoOSA4=
 github.com/pingcap/log v1.1.1-0.20241212030209-7e3ff8601a2a h1:WIhmJBlNGmnCWH6TLMdZfNEDaiU8cFpZe3iaqDbQ0M8=
@@ -1485,8 +1485,8 @@ github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
 github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
 github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
 github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
-github.com/tikv/pd/client v0.0.0-20250213082949-e8930327be42 h1:hvB0tf4u5ZU1vAew3MmbyxdYuogDLjIZYzSFt1ACFqo=
-github.com/tikv/pd/client v0.0.0-20250213082949-e8930327be42/go.mod h1:veL5JbFL99G5cvS/Q2cLiFQklIiSrVgsBCwFnXc+Zgo=
+github.com/tikv/pd/client v0.0.0-20250318085533-e8050f72d00d h1:2D+HY8hUlNz+GESWS4IwTBiZVbprvm4TSx3AbFJ46MM=
+github.com/tikv/pd/client v0.0.0-20250318085533-e8050f72d00d/go.mod h1:6fHHp8ecZIIkGyjxKn/oZFqX5dzrRkcHjFJPlBpigzQ=
 github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs=
 github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
 github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
diff --git a/integration_tests/split_test.go b/integration_tests/split_test.go
index 08bc75d..cc066af 100644
--- a/integration_tests/split_test.go
+++ b/integration_tests/split_test.go
@@ -166,7 +166,7 @@ func (c *mockPDClient) disable() {
 	c.stop = true
 }
 
-func (c *mockPDClient) GetAllMembers(ctx context.Context) ([]*pdpb.Member, error) {
+func (c *mockPDClient) GetAllMembers(ctx context.Context) (*pdpb.GetMembersResponse, error) {
 	return nil, nil
 }
 
diff --git a/internal/locate/region_request_test.go b/internal/locate/region_request_test.go
index 0719c2c..46e067e 100644
--- a/internal/locate/region_request_test.go
+++ b/internal/locate/region_request_test.go
@@ -962,7 +962,8 @@ func (s *testRegionRequestToSingleStoreSuite) TestRegionRequestValidateReadTS()
 	testImpl(getTS, true, nil)
 	testImpl(func() uint64 { return addTS(getTS(), -time.Minute) }, false, nil)
 	testImpl(func() uint64 { return addTS(getTS(), -time.Minute) }, true, nil)
-	testImpl(func() uint64 { return addTS(getTS(), +time.Minute) }, false, oracle.ErrFutureTSRead{})
+	// check is skipped for normal read
+	testImpl(func() uint64 { return addTS(getTS(), +time.Minute) }, false, nil)
 	testImpl(func() uint64 { return addTS(getTS(), +time.Minute) }, true, oracle.ErrFutureTSRead{})
 	testImpl(func() uint64 { return math.MaxUint64 }, false, nil)
 	testImpl(func() uint64 { return math.MaxUint64 }, true, oracle.ErrLatestStaleRead{})
diff --git a/oracle/oracles/pd_test.go b/oracle/oracles/pd_test.go
index 01c67c5..b4c4d62 100644
--- a/oracle/oracles/pd_test.go
+++ b/oracle/oracles/pd_test.go
@@ -36,15 +36,20 @@ package oracles
 
 import (
 	"context"
+	"fmt"
 	"math"
 	"sync"
 	"sync/atomic"
 	"testing"
 	"time"
 
+	"github.com/pingcap/failpoint"
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 	"github.com/tikv/client-go/v2/oracle"
+	"github.com/tikv/client-go/v2/util"
 	pd "github.com/tikv/pd/client"
+	"github.com/tikv/pd/client/pkg/caller"
 )
 
 func TestPDOracle_UntilExpired(t *testing.T) {
@@ -87,6 +92,10 @@ func (c *MockPdClient) GetTS(ctx context.Context) (int64, int64, error) {
 	return 0, c.logicalTimestamp.Add(1), nil
 }
 
+func (c *MockPdClient) WithCallerComponent(component caller.Component) pd.Client {
+	return c
+}
+
 func TestPdOracle_SetLowResolutionTimestampUpdateInterval(t *testing.T) {
 	pdClient := MockPdClient{}
 	o := NewPdOracleWithClient(&pdClient)
@@ -374,10 +383,15 @@ func TestValidateReadTS(t *testing.T) {
 		// the fetching-from-PD path, and it can get the previous ts + 1, which can allow this validation to pass.
 		err = o.ValidateReadTS(ctx, ts+1, staleRead, opt)
 		assert.NoError(t, err)
-		// It can't pass if the readTS is newer than previous ts + 2.
+		// It can also pass if the readTS is previous ts + 2, as it can perform a retry.
 		ts, err = o.GetTimestamp(ctx, opt)
 		assert.NoError(t, err)
 		err = o.ValidateReadTS(ctx, ts+2, staleRead, opt)
+		assert.NoError(t, err)
+		// As it retries at most once, it can't pass the check if the readTS is newer than previous ts + 3
+		ts, err = o.GetTimestamp(ctx, opt)
+		assert.NoError(t, err)
+		err = o.ValidateReadTS(ctx, ts+3, staleRead, opt)
 		assert.Error(t, err)
 
 		// Simulate other PD clients requests a timestamp.
@@ -389,7 +403,6 @@ func TestValidateReadTS(t *testing.T) {
 	}
 
 	testImpl(true)
-	testImpl(false)
 }
 
 type MockPDClientWithPause struct {
@@ -411,7 +424,13 @@ func (c *MockPDClientWithPause) Resume() {
 	c.mu.Unlock()
 }
 
+func (c *MockPDClientWithPause) WithCallerComponent(component caller.Component) pd.Client {
+	return c
+}
+
 func TestValidateReadTSForStaleReadReusingGetTSResult(t *testing.T) {
+	util.EnableFailpoints()
+
 	pdClient := &MockPDClientWithPause{}
 	o, err := NewPdOracle(pdClient, &PDOracleOptions{
 		UpdateInterval: time.Second * 2,
@@ -420,6 +439,11 @@ func TestValidateReadTSForStaleReadReusingGetTSResult(t *testing.T) {
 	assert.NoError(t, err)
 	defer o.Close()
 
+	assert.NoError(t, failpoint.Enable("tikvclient/validateReadTSRetryGetTS", `return("skip")`))
+	defer func() {
+		assert.NoError(t, failpoint.Disable("tikvclient/validateReadTSRetryGetTS"))
+	}()
+
 	asyncValidate := func(ctx context.Context, readTS uint64) chan error {
 		ch := make(chan error, 1)
 		go func() {
@@ -429,21 +453,21 @@ func TestValidateReadTSForStaleReadReusingGetTSResult(t *testing.T) {
 		return ch
 	}
 
-	noResult := func(ch chan error) {
+	noResult := func(ch chan error, additionalMsg ...interface{}) {
 		select {
 		case <-ch:
-			assert.FailNow(t, "a ValidateReadTS operation is not blocked while it's expected to be blocked")
+			assert.FailNow(t, "a ValidateReadTS operation is not blocked while it's expected to be blocked", additionalMsg...)
 		default:
 		}
 	}
 
 	cancelIndices := []int{-1, -1, 0, 1}
-	for i, ts := range []uint64{100, 200, 300, 400} {
+	for caseIndex, ts := range []uint64{100, 200, 300, 400} {
 		// Note: the ts is the result that the next GetTS will return. Any validation with readTS <= ts should pass, otherwise fail.
 
 		// We will cancel the cancelIndex-th validation call. This is for testing that canceling some of the calls
-		// doesn't affect other calls that are waiting
-		cancelIndex := cancelIndices[i]
+		// doesn't affect other calls that are waiting.
+		cancelIndex := cancelIndices[caseIndex]
 
 		pdClient.Pause()
 
@@ -541,13 +565,19 @@ func TestValidateReadTSForNormalReadDoNotAffectUpdateInterval(t *testing.T) {
 	assert.NoError(t, err)
 	mustNoNotify()
 
-	// It loads `ts + 1` from the mock PD, and the check cannot pass.
+	// It loads `ts + 1` from the mock PD, and then retries `ts + 2` and passes.
 	err = o.ValidateReadTS(ctx, ts+2, false, opt)
-	assert.Error(t, err)
+	assert.NoError(t, err)
 	mustNoNotify()
 
-	// Do the check again. It loads `ts + 2` from the mock PD, and the check passes.
-	err = o.ValidateReadTS(ctx, ts+2, false, opt)
+	// It loads `ts + 3` and `ts + 4` from the mock PD, and the check cannot pass.
+	// Updated: 2025-03-12, the non-stale read check is temporarily skipped.
+	err = o.ValidateReadTS(ctx, ts+5, false, opt)
+	assert.NoError(t, err)
+	mustNoNotify()
+
+	// Do the check again. It loads `ts + 5` from the mock PD, and the check passes.
+	err = o.ValidateReadTS(ctx, ts+5, false, opt)
 	assert.NoError(t, err)
 	mustNoNotify()
 }
@@ -586,3 +616,71 @@ func TestSetLastTSAlwaysPushTS(t *testing.T) {
 	close(cancel)
 	wg.Wait()
 }
+
+func TestValidateReadTSFromDifferentSource(t *testing.T) {
+	// Updated: 2025-03-12, the non-stale read check is temporarily skipped.
+	t.Skip()
+
+	// If a ts is fetched from a different client to the same cluster, the ts might not be cached by the low resolution
+	// ts. In this case, the validation should not be false positive.
+	util.EnableFailpoints()
+	pdClient := MockPdClient{}
+	o, err := NewPdOracle(&pdClient, &PDOracleOptions{
+		UpdateInterval: time.Second * 2,
+		NoUpdateTS:     true,
+	})
+	assert.NoError(t, err)
+	defer o.Close()
+
+	// Construct the situation that the low resolution ts is lower than the ts fetched from another client.
+	ts, err := o.GetTimestamp(context.Background(), &oracle.Option{TxnScope: oracle.GlobalTxnScope})
+	assert.NoError(t, err)
+	lowResolutionTS, err := o.GetLowResolutionTimestamp(context.Background(), &oracle.Option{TxnScope: oracle.GlobalTxnScope})
+	assert.NoError(t, err)
+	assert.Equal(t, ts, lowResolutionTS)
+
+	assert.NoError(t, failpoint.Enable("tikvclient/getCurrentTSForValidationBeforeReturn", "pause"))
+	defer func() {
+		assert.NoError(t, failpoint.Disable("tikvclient/getCurrentTSForValidationBeforeReturn"))
+	}()
+
+	// Trigger getting ts from PD for validation, which causes a previously-started concurrent call. We block it during
+	// getting the ts by the failpoint. So that when the second call starts, it will reuse the same singleflight
+	// for getting the ts, which return a older ts to it.
+	firstResCh := make(chan error)
+	go func() {
+		firstResCh <- o.ValidateReadTS(context.Background(), ts+1, false, &oracle.Option{TxnScope: oracle.GlobalTxnScope})
+	}()
+
+	select {
+	case err = <-firstResCh:
+		assert.FailNow(t, fmt.Sprintf("expected to be blocked, but got result: %v", err))
+	case <-time.After(time.Millisecond * 50):
+	}
+
+	pdClient.logicalTimestamp.Add(10)
+	physical, logical, err := pdClient.GetTS(context.Background())
+	assert.NoError(t, err)
+	// The next ts should be the previous `ts + 1 (fetched by the ValidateReadTS call) + 10 (advanced manually) + 1`.
+	nextTS := oracle.ComposeTS(physical, logical)
+	// The low resolution ts is not updated since the validation.
+	nextLowResolutionTS, err := o.GetLowResolutionTimestamp(context.Background(), &oracle.Option{TxnScope: oracle.GlobalTxnScope})
+	assert.NoError(t, err)
+	assert.Equal(t, ts+1, nextLowResolutionTS)
+	assert.Equal(t, nextTS-11, nextLowResolutionTS)
+
+	// The second check reuses the singleflight to get the ts and the result can be older than `nextTS`.
+	secondResCh := make(chan error)
+	go func() {
+		secondResCh <- o.ValidateReadTS(context.Background(), nextTS, false, &oracle.Option{TxnScope: oracle.GlobalTxnScope})
+	}()
+	select {
+	case err = <-firstResCh:
+		assert.FailNow(t, fmt.Sprintf("expected to be blocked, but got result: %v", err))
+	case <-time.After(time.Millisecond * 50):
+	}
+
+	assert.NoError(t, failpoint.Disable("tikvclient/getCurrentTSForValidationBeforeReturn"))
+	require.NoError(t, <-firstResCh)
+	require.NoError(t, <-secondResCh)
+}