diff --git a/.bazelversion b/.bazelversion new file mode 100644 index 0000000000000..815da58b7a9ed --- /dev/null +++ b/.bazelversion @@ -0,0 +1 @@ +7.4.1 diff --git a/pkg/statistics/handle/BUILD.bazel b/pkg/statistics/handle/BUILD.bazel index 730857e8f25bb..2647b9cfae81d 100644 --- a/pkg/statistics/handle/BUILD.bazel +++ b/pkg/statistics/handle/BUILD.bazel @@ -59,7 +59,7 @@ go_test( embed = [":handle"], flaky = True, race = "on", - shard_count = 9, + shard_count = 10, deps = [ "//pkg/config", "//pkg/parser/model", diff --git a/pkg/statistics/handle/handle_hist.go b/pkg/statistics/handle/handle_hist.go index ea56f94c5c741..217c271ae759f 100644 --- a/pkg/statistics/handle/handle_hist.go +++ b/pkg/statistics/handle/handle_hist.go @@ -41,7 +41,7 @@ import ( ) // RetryCount is the max retry count for a sync load task. -const RetryCount = 3 +const RetryCount = 2 var globalStatsSyncLoadSingleFlight singleflight.Group @@ -98,9 +98,13 @@ func (h *Handle) SendLoadRequests(sc *stmtctx.StatementContext, neededHistItems } select { case h.StatsLoad.NeededItemsCh <- task: - result, ok := <-task.ResultCh - intest.Assert(ok, "task.ResultCh cannot be closed") - return result, nil + select { + case <-timer.C: + return nil, errors.New("sync load took too long to return") + case result, ok := <-task.ResultCh: + intest.Assert(ok, "task.ResultCh cannot be closed") + return result, nil + } case <-timer.C: return nil, errors.New("sync load stats channel is full and timeout sending task to channel") } diff --git a/pkg/statistics/handle/handle_hist_test.go b/pkg/statistics/handle/handle_hist_test.go index c8c78b7df0aa5..22cfc79656dfc 100644 --- a/pkg/statistics/handle/handle_hist_test.go +++ b/pkg/statistics/handle/handle_hist_test.go @@ -343,3 +343,47 @@ func TestRetry(t *testing.T) { } require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/pkg/statistics/handle/mockReadStatsForOneFail")) } + +func TestSendLoadRequestsWaitTooLong(t *testing.T) { + originConfig := config.GetGlobalConfig() + newConfig := config.NewConfig() + newConfig.Performance.StatsLoadConcurrency = 0 // no worker to consume channel + newConfig.Performance.StatsLoadQueueSize = 10000 + config.StoreGlobalConfig(newConfig) + defer config.StoreGlobalConfig(originConfig) + store, dom := testkit.CreateMockStoreAndDomain(t) + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t(a int, b int, c int, primary key(a), key idx(b,c))") + tk.MustExec("insert into t values (1,1,1),(2,2,2),(3,3,3)") + + oriLease := dom.StatsHandle().Lease() + dom.StatsHandle().SetLease(1) + defer func() { + dom.StatsHandle().SetLease(oriLease) + }() + tk.MustExec("analyze table t all columns") + h := dom.StatsHandle() + is := dom.InfoSchema() + tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err) + tableInfo := tbl.Meta() + neededColumns := make([]model.TableItemID, 0, len(tableInfo.Columns)) + for _, col := range tableInfo.Columns { + neededColumns = append(neededColumns, model.TableItemID{TableID: tableInfo.ID, ID: col.ID, IsIndex: false}) + } + stmtCtx := stmtctx.NewStmtCtx() + timeout := time.Nanosecond * 100 + require.NoError(t, h.SendLoadRequests(stmtCtx, neededColumns, timeout)) + for _, resultCh := range stmtCtx.StatsLoad.ResultCh { + rs1 := <-resultCh + require.Error(t, rs1.Err) + } + stmtCtx1 := stmtctx.NewStmtCtx() + require.NoError(t, h.SendLoadRequests(stmtCtx1, neededColumns, timeout)) + for _, resultCh := range stmtCtx1.StatsLoad.ResultCh { + rs1 := <-resultCh + require.Error(t, rs1.Err) + } +}