diff --git a/statistics/handle/BUILD.bazel b/statistics/handle/BUILD.bazel index 81dff92c5b143..d52847495d539 100644 --- a/statistics/handle/BUILD.bazel +++ b/statistics/handle/BUILD.bazel @@ -42,6 +42,7 @@ go_library( "//util/memory", "//util/ranger", "//util/sqlexec", + "//util/syncutil", "//util/timeutil", "@com_github_ngaut_pools//:pools", "@com_github_pingcap_errors//:errors", @@ -72,6 +73,7 @@ go_test( ], embed = [":handle"], flaky = True, + race = "on", shard_count = 50, deps = [ "//config", diff --git a/statistics/handle/handle.go b/statistics/handle/handle.go index 79a5382779208..fc4f86dc54fb8 100644 --- a/statistics/handle/handle.go +++ b/statistics/handle/handle.go @@ -48,6 +48,7 @@ import ( "github.com/pingcap/tidb/util/mathutil" "github.com/pingcap/tidb/util/memory" "github.com/pingcap/tidb/util/sqlexec" + "github.com/pingcap/tidb/util/syncutil" "github.com/prometheus/client_golang/prometheus" "github.com/tikv/client-go/v2/oracle" atomic2 "go.uber.org/atomic" @@ -70,7 +71,7 @@ type Handle struct { initStatsCtx sessionctx.Context mu struct { - sync.RWMutex + syncutil.RWMutex ctx sessionctx.Context // rateMap contains the error rate delta from feedback. rateMap errorRateDeltaMap @@ -361,8 +362,15 @@ func (h *Handle) RemoveLockedTables(tids []int64, pids []int64, tables []*ast.Ta return "", err } -// IsTableLocked check whether table is locked in handle +// IsTableLocked check whether table is locked in handle with Handle.Mutex func (h *Handle) IsTableLocked(tableID int64) bool { + h.mu.RLock() + defer h.mu.RUnlock() + return h.isTableLocked(tableID) +} + +// IsTableLocked check whether table is locked in handle without Handle.Mutex +func (h *Handle) isTableLocked(tableID int64) bool { return isTableLocked(h.tableLocked, tableID) } diff --git a/statistics/handle/update.go b/statistics/handle/update.go index 68aa9cebbcf05..e245a3ea0bca5 100644 --- a/statistics/handle/update.go +++ b/statistics/handle/update.go @@ -549,7 +549,8 @@ func (h *Handle) dumpTableStatCountToKV(id int64, delta variable.TableDelta) (up startTS := txn.StartTS() updateStatsMeta := func(id int64) error { var err error - if h.IsTableLocked(id) { + // This lock is already locked on it so it use isTableLocked without lock. + if h.isTableLocked(id) { if delta.Delta < 0 { _, err = exec.ExecuteInternal(ctx, "update mysql.stats_table_locked set version = %?, count = count - %?, modify_count = modify_count + %? where table_id = %? and count >= %?", startTS, -delta.Delta, delta.Count, id, -delta.Delta) } else {