@@ -543,49 +543,42 @@ func (s *KVStore) safeTSUpdater() {
543
543
}
544
544
545
545
func (s * KVStore ) updateSafeTS (ctx context.Context ) {
546
+ // Try to get the cluster-level minimum resolved timestamp from PD first.
547
+ if s .setClusterMinSafeTSByPD (ctx ) {
548
+ return
549
+ }
550
+
546
551
stores := s .regionCache .GetStoresByType (tikvrpc .TiKV )
547
552
tikvClient := s .GetTiKVClient ()
548
553
wg := & sync.WaitGroup {}
549
554
wg .Add (len (stores ))
555
+ // If getting the cluster-level minimum resolved timestamp from PD failed or returned 0,
556
+ // try to get it from TiKV.
550
557
for _ , store := range stores {
551
558
storeID := store .StoreID ()
552
559
storeAddr := store .GetAddr ()
553
560
go func (ctx context.Context , wg * sync.WaitGroup , storeID uint64 , storeAddr string ) {
554
561
defer wg .Done ()
555
562
556
- var (
557
- safeTS uint64
558
- err error
563
+ resp , err := tikvClient .SendRequest (
564
+ ctx , storeAddr , tikvrpc .NewRequest (
565
+ tikvrpc .CmdStoreSafeTS , & kvrpcpb.StoreSafeTSRequest {
566
+ KeyRange : & kvrpcpb.KeyRange {
567
+ StartKey : []byte ("" ),
568
+ EndKey : []byte ("" ),
569
+ },
570
+ }, kvrpcpb.Context {
571
+ RequestSource : util .RequestSourceFromCtx (ctx ),
572
+ },
573
+ ), client .ReadTimeoutShort ,
559
574
)
560
575
storeIDStr := strconv .Itoa (int (storeID ))
561
- // Try to get the minimum resolved timestamp of the store from PD.
562
- if s .pdHttpClient != nil {
563
- safeTS , err = s .pdHttpClient .GetStoreMinResolvedTS (ctx , storeID )
564
- if err != nil {
565
- logutil .BgLogger ().Debug ("get resolved TS from PD failed" , zap .Error (err ), zap .Uint64 ("store-id" , storeID ))
566
- }
567
- }
568
- // If getting the minimum resolved timestamp from PD failed or returned 0, try to get it from TiKV.
569
- if safeTS == 0 || err != nil {
570
- resp , err := tikvClient .SendRequest (
571
- ctx , storeAddr , tikvrpc .NewRequest (
572
- tikvrpc .CmdStoreSafeTS , & kvrpcpb.StoreSafeTSRequest {
573
- KeyRange : & kvrpcpb.KeyRange {
574
- StartKey : []byte ("" ),
575
- EndKey : []byte ("" ),
576
- },
577
- }, kvrpcpb.Context {
578
- RequestSource : util .RequestSourceFromCtx (ctx ),
579
- },
580
- ), client .ReadTimeoutShort ,
581
- )
582
- if err != nil {
583
- metrics .TiKVSafeTSUpdateCounter .WithLabelValues ("fail" , storeIDStr ).Inc ()
584
- logutil .BgLogger ().Debug ("update safeTS failed" , zap .Error (err ), zap .Uint64 ("store-id" , storeID ))
585
- return
586
- }
587
- safeTS = resp .Resp .(* kvrpcpb.StoreSafeTSResponse ).GetSafeTs ()
576
+ if err != nil {
577
+ metrics .TiKVSafeTSUpdateCounter .WithLabelValues ("fail" , storeIDStr ).Inc ()
578
+ logutil .BgLogger ().Debug ("update safeTS failed" , zap .Error (err ), zap .Uint64 ("store-id" , storeID ))
579
+ return
588
580
}
581
+ safeTS := resp .Resp .(* kvrpcpb.StoreSafeTSResponse ).GetSafeTs ()
589
582
590
583
_ , preSafeTS := s .getSafeTS (storeID )
591
584
if preSafeTS > safeTS {
@@ -615,6 +608,40 @@ func (s *KVStore) updateSafeTS(ctx context.Context) {
615
608
wg .Wait ()
616
609
}
617
610
611
+ var (
612
+ skipClusterSafeTSUpdateCounter = metrics .TiKVSafeTSUpdateCounter .WithLabelValues ("skip" , "cluster" )
613
+ successClusterSafeTSUpdateCounter = metrics .TiKVSafeTSUpdateCounter .WithLabelValues ("success" , "cluster" )
614
+ clusterMinSafeTSGap = metrics .TiKVMinSafeTSGapSeconds .WithLabelValues ("cluster" )
615
+ )
616
+
617
+ // setClusterMinSafeTSByPD try to get cluster-level's min resolved timestamp from PD when @@txn_scope is `global`.
618
+ func (s * KVStore ) setClusterMinSafeTSByPD (ctx context.Context ) bool {
619
+ isGlobal := config .GetTxnScopeFromConfig () == oracle .GlobalTxnScope
620
+ // Try to get the minimum resolved timestamp of the cluster from PD.
621
+ if s .pdHttpClient != nil && isGlobal {
622
+ clusterMinSafeTS , err := s .pdHttpClient .GetClusterMinResolvedTS (ctx )
623
+ if err != nil {
624
+ logutil .BgLogger ().Debug ("get cluster-level min resolved timestamp from PD failed" , zap .Error (err ))
625
+ } else if clusterMinSafeTS != 0 {
626
+ // Update metrics.
627
+ preClusterMinSafeTS := s .GetMinSafeTS (oracle .GlobalTxnScope )
628
+ if preClusterMinSafeTS > clusterMinSafeTS {
629
+ skipClusterSafeTSUpdateCounter .Inc ()
630
+ preSafeTSTime := oracle .GetTimeFromTS (preClusterMinSafeTS )
631
+ clusterMinSafeTSGap .Set (time .Since (preSafeTSTime ).Seconds ())
632
+ } else {
633
+ s .minSafeTS .Store (oracle .GlobalTxnScope , clusterMinSafeTS )
634
+ successClusterSafeTSUpdateCounter .Inc ()
635
+ safeTSTime := oracle .GetTimeFromTS (clusterMinSafeTS )
636
+ clusterMinSafeTSGap .Set (time .Since (safeTSTime ).Seconds ())
637
+ }
638
+ return true
639
+ }
640
+ }
641
+
642
+ return false
643
+ }
644
+
618
645
// Variables defines the variables used by TiKV storage.
619
646
type Variables = kv.Variables
620
647
0 commit comments