diff --git a/domain/BUILD.bazel b/domain/BUILD.bazel index 56e3bffedde31..88ea6a98a728a 100644 --- a/domain/BUILD.bazel +++ b/domain/BUILD.bazel @@ -113,13 +113,16 @@ go_test( "//metrics", "//parser/ast", "//parser/model", + "//parser/mysql", "//parser/terror", "//server", "//session", + "//sessionctx/stmtctx", "//sessionctx/variable", "//store/mockstore", "//testkit", "//testkit/testsetup", + "//types", "//util", "//util/mock", "@com_github_ngaut_pools//:pools", diff --git a/domain/domain.go b/domain/domain.go index f01cbbfb326bd..67ec0eb3f5449 100644 --- a/domain/domain.go +++ b/domain/domain.go @@ -118,10 +118,15 @@ type Domain struct { indexUsageSyncLease time.Duration dumpFileGcChecker *dumpFileGcChecker planReplayerHandle *planReplayerHandle - expiredTimeStamp4PC types.Time - logBackupAdvancer *daemon.OwnerDaemon - historicalStatsWorker *HistoricalStatsWorker - ttlJobManager *ttlworker.JobManager + expiredTimeStamp4PC struct { + // let `expiredTimeStamp4PC` use its own lock to avoid any block across domain.Reload() + // and compiler.Compile(), see issue https://github.com/pingcap/tidb/issues/45400 + sync.RWMutex + expiredTimeStamp types.Time + } + logBackupAdvancer *daemon.OwnerDaemon + historicalStatsWorker *HistoricalStatsWorker + ttlJobManager *ttlworker.JobManager serverID uint64 serverIDSession *concurrency.Session @@ -394,18 +399,18 @@ func (do *Domain) GetSnapshotMeta(startTS uint64) (*meta.Meta, error) { // ExpiredTimeStamp4PC gets expiredTimeStamp4PC from domain. func (do *Domain) ExpiredTimeStamp4PC() types.Time { - do.m.Lock() - defer do.m.Unlock() + do.expiredTimeStamp4PC.RLock() + defer do.expiredTimeStamp4PC.RUnlock() - return do.expiredTimeStamp4PC + return do.expiredTimeStamp4PC.expiredTimeStamp } // SetExpiredTimeStamp4PC sets the expiredTimeStamp4PC from domain. func (do *Domain) SetExpiredTimeStamp4PC(time types.Time) { - do.m.Lock() - defer do.m.Unlock() + do.expiredTimeStamp4PC.Lock() + defer do.expiredTimeStamp4PC.Unlock() - do.expiredTimeStamp4PC = time + do.expiredTimeStamp4PC.expiredTimeStamp = time } // DDL gets DDL from domain. @@ -898,7 +903,6 @@ func NewDomain(store kv.Storage, ddlLease time.Duration, statsLease time.Duratio slowQuery: newTopNSlowQueries(30, time.Hour*24*7, 500), indexUsageSyncLease: idxUsageSyncLease, dumpFileGcChecker: &dumpFileGcChecker{gcLease: dumpFileGcLease, paths: []string{GetPlanReplayerDirName(), GetOptimizerTraceDirName()}}, - expiredTimeStamp4PC: types.NewTime(types.ZeroCoreTime, mysql.TypeTimestamp, types.DefaultFsp), mdlCheckTableInfo: &mdlCheckTableInfo{ mu: sync.Mutex{}, jobsVerMap: make(map[int64]int64), @@ -913,6 +917,7 @@ func NewDomain(store kv.Storage, ddlLease time.Duration, statsLease time.Duratio do.serverMemoryLimitHandle = servermemorylimit.NewServerMemoryLimitHandle(do.exit) do.sysProcesses = SysProcesses{mu: &sync.RWMutex{}, procMap: make(map[uint64]sessionctx.Context)} do.initDomainSysVars() + do.expiredTimeStamp4PC.expiredTimeStamp = types.NewTime(types.ZeroCoreTime, mysql.TypeTimestamp, types.DefaultFsp) return do } diff --git a/domain/domain_test.go b/domain/domain_test.go index bd9287fe730ec..5ae256a277fb4 100644 --- a/domain/domain_test.go +++ b/domain/domain_test.go @@ -34,8 +34,11 @@ import ( "github.com/pingcap/tidb/metrics" "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/model" + "github.com/pingcap/tidb/parser/mysql" + "github.com/pingcap/tidb/sessionctx/stmtctx" "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/store/mockstore" + "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/mock" dto "github.com/prometheus/client_model/go" "github.com/stretchr/testify/require" @@ -187,6 +190,17 @@ func TestStatWorkRecoverFromPanic(t *testing.T) { scope := dom.GetScope("status") require.Equal(t, variable.DefaultStatusVarScopeFlag, scope) + // default expiredTimeStamp4PC = "0000-00-00 00:00:00" + ts := types.NewTime(types.ZeroCoreTime, mysql.TypeTimestamp, types.DefaultFsp) + expiredTimeStamp := dom.ExpiredTimeStamp4PC() + require.Equal(t, expiredTimeStamp, ts) + + // set expiredTimeStamp4PC to "2023-08-02 12:15:00" + ts, _ = types.ParseTimestamp(&stmtctx.StatementContext{TimeZone: time.UTC}, "2023-08-02 12:15:00") + dom.SetExpiredTimeStamp4PC(ts) + expiredTimeStamp = dom.ExpiredTimeStamp4PC() + require.Equal(t, expiredTimeStamp, ts) + err = store.Close() require.NoError(t, err)