From 5f1fa9f4f82e8beefb847efc7370bf494816ca02 Mon Sep 17 00:00:00 2001 From: Weizhen Wang Date: Thu, 27 Jul 2023 17:46:35 +0800 Subject: [PATCH] statistics: improve statslock test (#45616) ref pingcap/tidb#44940 --- statistics/handle/handletest/BUILD.bazel | 2 +- statistics/handle/handletest/handle_test.go | 116 -------------- .../handle/handletest/statslock/BUILD.bazel | 20 +++ .../handle/handletest/statslock/main_test.go | 33 ++++ .../handletest/statslock/stats_lcok_test.go | 142 ++++++++++++++++++ 5 files changed, 196 insertions(+), 117 deletions(-) create mode 100644 statistics/handle/handletest/statslock/BUILD.bazel create mode 100644 statistics/handle/handletest/statslock/main_test.go create mode 100644 statistics/handle/handletest/statslock/stats_lcok_test.go diff --git a/statistics/handle/handletest/BUILD.bazel b/statistics/handle/handletest/BUILD.bazel index 9bd93de37286b..acd2fc075afba 100644 --- a/statistics/handle/handletest/BUILD.bazel +++ b/statistics/handle/handletest/BUILD.bazel @@ -9,7 +9,7 @@ go_test( ], flaky = True, race = "on", - shard_count = 47, + shard_count = 45, deps = [ "//config", "//domain", diff --git a/statistics/handle/handletest/handle_test.go b/statistics/handle/handletest/handle_test.go index eb7b474785cc9..a8d8df02166d6 100644 --- a/statistics/handle/handletest/handle_test.go +++ b/statistics/handle/handletest/handle_test.go @@ -1726,122 +1726,6 @@ func TestUninitializedStatsStatus(t *testing.T) { checkStatsPseudo() } -func TestStatsLockAndUnlockTable(t *testing.T) { - restore := config.RestoreFunc() - defer restore() - config.UpdateGlobal(func(conf *config.Config) { - conf.Performance.EnableStatsCacheMemQuota = true - }) - store, dom := testkit.CreateMockStoreAndDomain(t) - tk := testkit.NewTestKit(t, store) - tk.MustExec("set @@tidb_analyze_version = 1") - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a int, b varchar(10), index idx_b (b))") - tk.MustExec("analyze table test.t") - tbl, err := dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - require.Nil(t, err) - - handle := domain.GetDomain(tk.Session()).StatsHandle() - tblStats := handle.GetTableStats(tbl.Meta()) - for _, col := range tblStats.Columns { - require.True(t, col.IsStatsInitialized()) - } - tk.MustExec("lock stats t") - - rows := tk.MustQuery("select count(*) from mysql.stats_table_locked").Rows() - num, _ := strconv.Atoi(rows[0][0].(string)) - require.Equal(t, num, 1) - - tk.MustExec("insert into t(a, b) values(1,'a')") - tk.MustExec("insert into t(a, b) values(2,'b')") - - tk.MustExec("analyze table test.t") - tblStats1 := handle.GetTableStats(tbl.Meta()) - require.Equal(t, tblStats, tblStats1) - - tableLocked1 := handle.GetTableLockedAndClearForTest() - err = handle.LoadLockedTables() - require.Nil(t, err) - tableLocked2 := handle.GetTableLockedAndClearForTest() - require.Equal(t, tableLocked1, tableLocked2) - - tk.MustExec("unlock stats t") - rows = tk.MustQuery("select count(*) from mysql.stats_table_locked").Rows() - num, _ = strconv.Atoi(rows[0][0].(string)) - require.Equal(t, num, 0) - - tk.MustExec("analyze table test.t") - tblStats2 := handle.GetTableStats(tbl.Meta()) - require.Equal(t, int64(2), tblStats2.RealtimeCount) -} - -func TestStatsLockAndUnlockTables(t *testing.T) { - restore := config.RestoreFunc() - defer restore() - config.UpdateGlobal(func(conf *config.Config) { - conf.Performance.EnableStatsCacheMemQuota = true - }) - store, dom := testkit.CreateMockStoreAndDomain(t) - tk := testkit.NewTestKit(t, store) - tk.MustExec("set @@tidb_analyze_version = 1") - tk.MustExec("use test") - tk.MustExec("drop table if exists t1") - tk.MustExec("drop table if exists t2") - tk.MustExec("create table t1(a int, b varchar(10), index idx_b (b))") - tk.MustExec("create table t2(a int, b varchar(10), index idx_b (b))") - tk.MustExec("analyze table test.t1, test.t2") - tbl1, err := dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) - require.Nil(t, err) - tbl2, err := dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t2")) - require.Nil(t, err) - - handle := domain.GetDomain(tk.Session()).StatsHandle() - tbl1Stats := handle.GetTableStats(tbl1.Meta()) - for _, col := range tbl1Stats.Columns { - require.True(t, col.IsStatsInitialized()) - } - tbl2Stats := handle.GetTableStats(tbl2.Meta()) - for _, col := range tbl2Stats.Columns { - require.True(t, col.IsStatsInitialized()) - } - - tk.MustExec("lock stats t1, t2") - - rows := tk.MustQuery("select count(*) from mysql.stats_table_locked").Rows() - num, _ := strconv.Atoi(rows[0][0].(string)) - require.Equal(t, num, 2) - - tk.MustExec("insert into t1(a, b) values(1,'a')") - tk.MustExec("insert into t1(a, b) values(2,'b')") - - tk.MustExec("insert into t2(a, b) values(1,'a')") - tk.MustExec("insert into t2(a, b) values(2,'b')") - - tk.MustExec("analyze table test.t1, test.t2") - tbl1Stats1 := handle.GetTableStats(tbl1.Meta()) - require.Equal(t, tbl1Stats, tbl1Stats1) - tbl2Stats1 := handle.GetTableStats(tbl2.Meta()) - require.Equal(t, tbl2Stats, tbl2Stats1) - - tableLocked1 := handle.GetTableLockedAndClearForTest() - err = handle.LoadLockedTables() - require.Nil(t, err) - tableLocked2 := handle.GetTableLockedAndClearForTest() - require.Equal(t, tableLocked1, tableLocked2) - - tk.MustExec("unlock stats test.t1, test.t2") - rows = tk.MustQuery("select count(*) from mysql.stats_table_locked").Rows() - num, _ = strconv.Atoi(rows[0][0].(string)) - require.Equal(t, num, 0) - - tk.MustExec("analyze table test.t1, test.t2") - tbl1Stats2 := handle.GetTableStats(tbl1.Meta()) - require.Equal(t, int64(2), tbl1Stats2.RealtimeCount) - tbl2Stats2 := handle.GetTableStats(tbl2.Meta()) - require.Equal(t, int64(2), tbl2Stats2.RealtimeCount) -} - func TestIssue39336(t *testing.T) { store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) diff --git a/statistics/handle/handletest/statslock/BUILD.bazel b/statistics/handle/handletest/statslock/BUILD.bazel new file mode 100644 index 0000000000000..78bea0e87a71c --- /dev/null +++ b/statistics/handle/handletest/statslock/BUILD.bazel @@ -0,0 +1,20 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_test") + +go_test( + name = "statslock_test", + timeout = "short", + srcs = [ + "main_test.go", + "stats_lcok_test.go", + ], + flaky = True, + deps = [ + "//config", + "//domain", + "//parser/model", + "//testkit", + "//testkit/testsetup", + "@com_github_stretchr_testify//require", + "@org_uber_go_goleak//:goleak", + ], +) diff --git a/statistics/handle/handletest/statslock/main_test.go b/statistics/handle/handletest/statslock/main_test.go new file mode 100644 index 0000000000000..422cd60aed1f7 --- /dev/null +++ b/statistics/handle/handletest/statslock/main_test.go @@ -0,0 +1,33 @@ +// Copyright 2023 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package statslock + +import ( + "testing" + + "github.com/pingcap/tidb/testkit/testsetup" + "go.uber.org/goleak" +) + +func TestMain(m *testing.M) { + opts := []goleak.Option{ + goleak.IgnoreTopFunction("github.com/golang/glog.(*fileSink).flushDaemon"), + goleak.IgnoreTopFunction("github.com/lestrrat-go/httprc.runFetchWorker"), + goleak.IgnoreTopFunction("go.etcd.io/etcd/client/pkg/v3/logutil.(*MergeLogger).outputLoop"), + goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"), + } + testsetup.SetupForCommonTest() + goleak.VerifyTestMain(m, opts...) +} diff --git a/statistics/handle/handletest/statslock/stats_lcok_test.go b/statistics/handle/handletest/statslock/stats_lcok_test.go new file mode 100644 index 0000000000000..8e1d6e598a8b6 --- /dev/null +++ b/statistics/handle/handletest/statslock/stats_lcok_test.go @@ -0,0 +1,142 @@ +// Copyright 2023 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package statslock + +import ( + "strconv" + "testing" + + "github.com/pingcap/tidb/config" + "github.com/pingcap/tidb/domain" + "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/testkit" + "github.com/stretchr/testify/require" +) + +func TestStatsLockAndUnlockTable(t *testing.T) { + restore := config.RestoreFunc() + defer restore() + config.UpdateGlobal(func(conf *config.Config) { + conf.Performance.EnableStatsCacheMemQuota = true + }) + store, dom := testkit.CreateMockStoreAndDomain(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("set @@tidb_analyze_version = 1") + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int, b varchar(10), index idx_b (b))") + tk.MustExec("analyze table test.t") + tbl, err := dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.Nil(t, err) + + handle := domain.GetDomain(tk.Session()).StatsHandle() + tblStats := handle.GetTableStats(tbl.Meta()) + for _, col := range tblStats.Columns { + require.True(t, col.IsStatsInitialized()) + } + tk.MustExec("lock stats t") + + rows := tk.MustQuery("select count(*) from mysql.stats_table_locked").Rows() + num, _ := strconv.Atoi(rows[0][0].(string)) + require.Equal(t, num, 1) + + tk.MustExec("insert into t(a, b) values(1,'a')") + tk.MustExec("insert into t(a, b) values(2,'b')") + + tk.MustExec("analyze table test.t") + tblStats1 := handle.GetTableStats(tbl.Meta()) + require.Equal(t, tblStats, tblStats1) + + tableLocked1 := handle.GetTableLockedAndClearForTest() + err = handle.LoadLockedTables() + require.Nil(t, err) + tableLocked2 := handle.GetTableLockedAndClearForTest() + require.Equal(t, tableLocked1, tableLocked2) + + tk.MustExec("unlock stats t") + rows = tk.MustQuery("select count(*) from mysql.stats_table_locked").Rows() + num, _ = strconv.Atoi(rows[0][0].(string)) + require.Equal(t, num, 0) + + tk.MustExec("analyze table test.t") + tblStats2 := handle.GetTableStats(tbl.Meta()) + require.Equal(t, int64(2), tblStats2.RealtimeCount) +} + +func TestStatsLockAndUnlockTables(t *testing.T) { + restore := config.RestoreFunc() + defer restore() + config.UpdateGlobal(func(conf *config.Config) { + conf.Performance.EnableStatsCacheMemQuota = true + }) + store, dom := testkit.CreateMockStoreAndDomain(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("set @@tidb_analyze_version = 1") + tk.MustExec("use test") + tk.MustExec("drop table if exists t1") + tk.MustExec("drop table if exists t2") + tk.MustExec("create table t1(a int, b varchar(10), index idx_b (b))") + tk.MustExec("create table t2(a int, b varchar(10), index idx_b (b))") + tk.MustExec("analyze table test.t1, test.t2") + tbl1, err := dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) + require.Nil(t, err) + tbl2, err := dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t2")) + require.Nil(t, err) + + handle := domain.GetDomain(tk.Session()).StatsHandle() + tbl1Stats := handle.GetTableStats(tbl1.Meta()) + for _, col := range tbl1Stats.Columns { + require.True(t, col.IsStatsInitialized()) + } + tbl2Stats := handle.GetTableStats(tbl2.Meta()) + for _, col := range tbl2Stats.Columns { + require.True(t, col.IsStatsInitialized()) + } + + tk.MustExec("lock stats t1, t2") + + rows := tk.MustQuery("select count(*) from mysql.stats_table_locked").Rows() + num, _ := strconv.Atoi(rows[0][0].(string)) + require.Equal(t, num, 2) + + tk.MustExec("insert into t1(a, b) values(1,'a')") + tk.MustExec("insert into t1(a, b) values(2,'b')") + + tk.MustExec("insert into t2(a, b) values(1,'a')") + tk.MustExec("insert into t2(a, b) values(2,'b')") + + tk.MustExec("analyze table test.t1, test.t2") + tbl1Stats1 := handle.GetTableStats(tbl1.Meta()) + require.Equal(t, tbl1Stats, tbl1Stats1) + tbl2Stats1 := handle.GetTableStats(tbl2.Meta()) + require.Equal(t, tbl2Stats, tbl2Stats1) + + tableLocked1 := handle.GetTableLockedAndClearForTest() + err = handle.LoadLockedTables() + require.Nil(t, err) + tableLocked2 := handle.GetTableLockedAndClearForTest() + require.Equal(t, tableLocked1, tableLocked2) + + tk.MustExec("unlock stats test.t1, test.t2") + rows = tk.MustQuery("select count(*) from mysql.stats_table_locked").Rows() + num, _ = strconv.Atoi(rows[0][0].(string)) + require.Equal(t, num, 0) + + tk.MustExec("analyze table test.t1, test.t2") + tbl1Stats2 := handle.GetTableStats(tbl1.Meta()) + require.Equal(t, int64(2), tbl1Stats2.RealtimeCount) + tbl2Stats2 := handle.GetTableStats(tbl2.Meta()) + require.Equal(t, int64(2), tbl2Stats2.RealtimeCount) +}