From ac6bc7ae45b54589d0c4c4448f02daa4bd5556cb Mon Sep 17 00:00:00 2001 From: Ti Chi Robot Date: Fri, 10 Nov 2023 19:00:43 +0800 Subject: [PATCH] statistics: avoid oom when to gc large stats_history (#48430) (#48489) close pingcap/tidb#48431 --- executor/historical_stats_test.go | 6 ++++-- statistics/handle/gc.go | 24 ++++++++++++++++++------ 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/executor/historical_stats_test.go b/executor/historical_stats_test.go index 4355dd6768f04..996ca85019ff5 100644 --- a/executor/historical_stats_test.go +++ b/executor/historical_stats_test.go @@ -237,8 +237,10 @@ func TestAssertHistoricalStatsAfterAlterTable(t *testing.T) { } func TestGCOutdatedHistoryStats(t *testing.T) { - failpoint.Enable("github.com/pingcap/tidb/domain/sendHistoricalStats", "return(true)") - defer failpoint.Disable("github.com/pingcap/tidb/domain/sendHistoricalStats") + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/domain/sendHistoricalStats", "return(true)")) + defer func() { + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/domain/sendHistoricalStats")) + }() store, dom := testkit.CreateMockStoreAndDomain(t) tk := testkit.NewTestKit(t, store) tk.MustExec("set global tidb_enable_historical_stats = 1") diff --git a/statistics/handle/gc.go b/statistics/handle/gc.go index a49f0ad65b5a0..e8aefc8f684e9 100644 --- a/statistics/handle/gc.go +++ b/statistics/handle/gc.go @@ -151,6 +151,14 @@ func (h *Handle) gcTableStats(is infoschema.InfoSchema, physicalID int64) error return nil } +func forCount(total int64, batch int64) int64 { + result := total / batch + if total%batch > 0 { + result++ + } + return result +} + // ClearOutdatedHistoryStats clear outdated historical stats func (h *Handle) ClearOutdatedHistoryStats() error { ctx := kv.WithInternalSourceType(context.Background(), kv.InternalTxnStats) @@ -172,15 +180,19 @@ func (h *Handle) ClearOutdatedHistoryStats() error { } count := rows[0].GetInt64(0) if count > 0 { - sql = "delete from mysql.stats_meta_history use index (idx_create_time) where create_time <= NOW() - INTERVAL %? SECOND" - _, err = exec.ExecuteInternal(ctx, sql, variable.HistoricalStatsDuration.Load().Seconds()) - if err != nil { + for n := int64(0); n < forCount(count, int64(1000)); n++ { + sql = "delete from mysql.stats_meta_history use index (idx_create_time) where create_time <= NOW() - INTERVAL %? SECOND limit 1000 " + _, err = exec.ExecuteInternal(ctx, sql, variable.HistoricalStatsDuration.Load().Seconds()) + if err != nil { + return err + } + } + for n := int64(0); n < forCount(count, int64(50)); n++ { + sql = "delete from mysql.stats_history use index (idx_create_time) where create_time <= NOW() - INTERVAL %? SECOND limit 50 " + _, err = exec.ExecuteInternal(ctx, sql, variable.HistoricalStatsDuration.Load().Seconds()) return err } - sql = "delete from mysql.stats_history use index (idx_create_time) where create_time <= NOW() - INTERVAL %? SECOND" - _, err = exec.ExecuteInternal(ctx, sql, variable.HistoricalStatsDuration.Load().Seconds()) logutil.BgLogger().Info("clear outdated historical stats") - return err } return nil }