@@ -17,6 +17,7 @@ package handle
17
17
import (
18
18
"context"
19
19
"encoding/json"
20
+ "strconv"
20
21
"time"
21
22
22
23
"github.com/pingcap/errors"
@@ -34,9 +35,11 @@ import (
34
35
"go.uber.org/zap"
35
36
)
36
37
38
+ const gcLastTSVarName = "tidb_stats_gc_last_ts"
39
+
37
40
// GCStats will garbage collect the useless stats info. For dropped tables, we will first update their version so that
38
41
// other tidb could know that table is deleted.
39
- func (h * Handle ) GCStats (is infoschema.InfoSchema , ddlLease time.Duration ) error {
42
+ func (h * Handle ) GCStats (is infoschema.InfoSchema , ddlLease time.Duration ) ( err error ) {
40
43
ctx := context .Background ()
41
44
// To make sure that all the deleted tables' schema and stats info have been acknowledged to all tidb,
42
45
// we only garbage collect version before 10 lease.
@@ -47,7 +50,17 @@ func (h *Handle) GCStats(is infoschema.InfoSchema, ddlLease time.Duration) error
47
50
return nil
48
51
}
49
52
gcVer := now - offset
50
- rows , _ , err := h .execRestrictedSQL (ctx , "select table_id from mysql.stats_meta where version < %?" , gcVer )
53
+ lastGC , err := h .GetLastGCTimestamp (ctx )
54
+ if err != nil {
55
+ return err
56
+ }
57
+ defer func () {
58
+ if err != nil {
59
+ return
60
+ }
61
+ err = h .writeGCTimestampToKV (ctx , gcVer )
62
+ }()
63
+ rows , _ , err := h .execRestrictedSQL (ctx , "select table_id from mysql.stats_meta where version >= %? and version < %?" , lastGC , gcVer )
51
64
if err != nil {
52
65
return errors .Trace (err )
53
66
}
@@ -70,6 +83,33 @@ func (h *Handle) GCStats(is infoschema.InfoSchema, ddlLease time.Duration) error
70
83
return h .removeDeletedExtendedStats (gcVer )
71
84
}
72
85
86
+ // GetLastGCTimestamp loads the last gc time from mysql.tidb.
87
+ func (h * Handle ) GetLastGCTimestamp (ctx context.Context ) (uint64 , error ) {
88
+ rows , _ , err := h .execRestrictedSQL (ctx , "SELECT HIGH_PRIORITY variable_value FROM mysql.tidb WHERE variable_name=%?" , gcLastTSVarName )
89
+ if err != nil {
90
+ return 0 , errors .Trace (err )
91
+ }
92
+ if len (rows ) == 0 {
93
+ return 0 , nil
94
+ }
95
+ lastGcTSString := rows [0 ].GetString (0 )
96
+ lastGcTS , err := strconv .ParseUint (lastGcTSString , 10 , 64 )
97
+ if err != nil {
98
+ return 0 , errors .Trace (err )
99
+ }
100
+ return lastGcTS , nil
101
+ }
102
+
103
+ func (h * Handle ) writeGCTimestampToKV (ctx context.Context , newTS uint64 ) error {
104
+ _ , _ , err := h .execRestrictedSQL (ctx ,
105
+ "insert into mysql.tidb (variable_name, variable_value) values (%?, %?) on duplicate key update variable_value = %?" ,
106
+ gcLastTSVarName ,
107
+ newTS ,
108
+ newTS ,
109
+ )
110
+ return err
111
+ }
112
+
73
113
func (h * Handle ) gcTableStats (is infoschema.InfoSchema , physicalID int64 ) error {
74
114
ctx := context .Background ()
75
115
rows , _ , err := h .execRestrictedSQL (ctx , "select is_index, hist_id from mysql.stats_histograms where table_id = %?" , physicalID )
0 commit comments