From 64dd762fde7c3d5f59ba07f0dffc5e577d31fb1d Mon Sep 17 00:00:00 2001 From: Jinlong Liu <50897894+King-Dylan@users.noreply.github.com> Date: Tue, 31 Dec 2024 02:18:33 -0800 Subject: [PATCH] planner: Fix load stats failure when stats file contains with `null` (#57818) close pingcap/tidb#53966 --- pkg/executor/load_stats.go | 4 ++ pkg/server/handler/optimizor/BUILD.bazel | 2 +- .../optimizor/statistics_handler_test.go | 58 +++++++++++++++++++ 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/pkg/executor/load_stats.go b/pkg/executor/load_stats.go index 33ef417262..a8f41ae5e3 100644 --- a/pkg/executor/load_stats.go +++ b/pkg/executor/load_stats.go @@ -83,6 +83,10 @@ func (e *LoadStatsInfo) Update(data []byte) error { if err := json.Unmarshal(data, jsonTbl); err != nil { return errors.Trace(err) } + // Check the `jsonTbl` in cases where the stats file with `null`. + if jsonTbl.TableName == "" && jsonTbl.Version == 0 { + return nil + } do := domain.GetDomain(e.Ctx) h := do.StatsHandle() if h == nil { diff --git a/pkg/server/handler/optimizor/BUILD.bazel b/pkg/server/handler/optimizor/BUILD.bazel index e91a85c639..6bd6840e56 100644 --- a/pkg/server/handler/optimizor/BUILD.bazel +++ b/pkg/server/handler/optimizor/BUILD.bazel @@ -43,7 +43,7 @@ go_test( "statistics_handler_test.go", ], flaky = True, - shard_count = 7, + shard_count = 8, deps = [ ":optimizor", "//pkg/config", diff --git a/pkg/server/handler/optimizor/statistics_handler_test.go b/pkg/server/handler/optimizor/statistics_handler_test.go index 56d8b5b9a8..1da7e245e2 100644 --- a/pkg/server/handler/optimizor/statistics_handler_test.go +++ b/pkg/server/handler/optimizor/statistics_handler_test.go @@ -346,3 +346,61 @@ func TestStatsPriorityQueueAPI(t *testing.T) { require.Empty(t, snapshot.CurrentJobs) require.Empty(t, snapshot.MustRetryTables) } + +// fix issue 53966 +func TestLoadNullStatsFile(t *testing.T) { + // Setting up the mock store + store := testkit.CreateMockStore(t) + + // Creating a new TiDB driver and client + driver := server2.NewTiDBDriver(store) + client := testserverclient.NewTestServerClient() + cfg := util.NewTestConfig() + cfg.Port = client.Port + cfg.Status.StatusPort = client.StatusPort + cfg.Status.ReportStatus = true + cfg.Socket = fmt.Sprintf("/tmp/tidb-mock-%d.sock", time.Now().UnixNano()) + + // Creating and running the server + server, err := server2.NewServer(cfg, driver) + require.NoError(t, err) + defer server.Close() + + dom, err := session.GetDomain(store) + require.NoError(t, err) + server.SetDomain(dom) + go func() { + err := server.Run(nil) + require.NoError(t, err) + }() + <-server2.RunInGoTestChan + client.Port = testutil.GetPortFromTCPAddr(server.ListenAddr()) + client.StatusPort = testutil.GetPortFromTCPAddr(server.StatusListenerAddr()) + client.WaitUntilServerOnline() + + // Creating the stats file + path := "/tmp/stats.json" + fp, err := os.Create(path) + require.NoError(t, err) + require.NotNil(t, fp) + defer func() { + require.NoError(t, fp.Close()) + require.NoError(t, os.Remove(path)) + }() + fp.Write([]byte("null")) + require.NoError(t, err) + + // Connecting to the database and executing SQL commands + db, err := sql.Open("mysql", client.GetDSN(func(config *mysql.Config) { + config.AllowAllFiles = true + config.Params["sql_mode"] = "''" + })) + require.NoError(t, err, "Error connecting") + tk := testkit.NewDBTestKit(t, db) + defer func() { + err := db.Close() + require.NoError(t, err) + }() + tk.MustExec("use test") + tk.MustExec(fmt.Sprintf("load stats '%s'", path)) +}