code: func (w *GCWorker) deleteRanges(ctx context.Context, safePoint uint64) error {
  	metrics.GCWorkerCounter.WithLabelValues("delete_range").Inc()
  
  	se := createSession(w.store)
  	ranges, err := util.LoadDeleteRanges(se, safePoint)
  	se.Close()
  	if err != nil {
  		return errors.Trace(err)
  	}
  
  	logutil.Logger(ctx).Info("[gc worker] start delete",
  		zap.String("uuid", w.uuid),
  		zap.Int("ranges", len(ranges)))
  	startTime := time.Now()
  	for _, r := range ranges {
  		startKey, endKey := r.Range()
  
  		err = w.sendUnsafeDestroyRangeRequest(ctx, startKey, endKey)
  		if err != nil {
  			return errors.Trace(err)
  		}
  
  		se := createSession(w.store)
  		err = util.CompleteDeleteRange(se, r)
  		se.Close()
  		if err != nil {
  			return errors.Trace(err)
  		}
  	}
  	logutil.Logger(ctx).Info("[gc worker] finish delete ranges",
  		zap.String("uuid", w.uuid),
  		zap.Int("num of ranges", len(ranges)),
  		zap.Duration("cost time", time.Since(startTime)))
  	metrics.GCHistogram.WithLabelValues("delete_ranges").Observe(time.Since(startTime).Seconds())
  	return nil
  }
docs: // deleteRanges processes all delete range records whose ts < safePoint in table `gc_delete_range`