diff --git a/cmd/tidb-server/main.go b/cmd/tidb-server/main.go index cd7da32550a4d..81908fd04a825 100644 --- a/cmd/tidb-server/main.go +++ b/cmd/tidb-server/main.go @@ -266,6 +266,7 @@ func main() { checkTempStorageQuota() } setupLog() + memory.InitMemoryHook() setupExtensions() setupStmtSummary() diff --git a/pkg/util/memory/meminfo.go b/pkg/util/memory/meminfo.go index a9d6aa3733d1b..0d7bd68a2bcbe 100644 --- a/pkg/util/memory/meminfo.go +++ b/pkg/util/memory/meminfo.go @@ -22,7 +22,9 @@ import ( "github.com/pingcap/sysutil" "github.com/pingcap/tidb/pkg/parser/terror" "github.com/pingcap/tidb/pkg/util/cgroup" + "github.com/pingcap/tidb/pkg/util/logutil" "github.com/shirou/gopsutil/v3/mem" + "go.uber.org/zap" ) // MemTotal returns the total amount of RAM on this system @@ -50,6 +52,10 @@ func MemTotalNormal() (uint64, error) { if time.Since(t) < 60*time.Second { return total, nil } + return memTotalNormal() +} + +func memTotalNormal() (uint64, error) { v, err := mem.VirtualMemory() if err != nil { return 0, err @@ -139,6 +145,7 @@ func MemUsedCGroup() (uint64, error) { return memo, nil } +// it is for test and init. func init() { if cgroup.InContainer() { MemTotal = MemTotalCGroup @@ -163,6 +170,37 @@ func init() { terror.MustNil(err) } +// InitMemoryHook initializes the memory hook. +// It is to solve the problem that tidb cannot read cgroup in the systemd. +// so if we are not in the container, we compare the cgroup memory limit and the physical memory, +// the cgroup memory limit is smaller, we use the cgroup memory hook. +func InitMemoryHook() { + if cgroup.InContainer() { + logutil.BgLogger().Info("use cgroup memory hook because TiDB is in the container") + return + } + cgroupValue, err := cgroup.GetMemoryLimit() + if err != nil { + return + } + physicalValue, err := memTotalNormal() + if err != nil { + return + } + if physicalValue > cgroupValue && cgroupValue != 0 { + MemTotal = MemTotalCGroup + MemUsed = MemUsedCGroup + sysutil.RegisterGetMemoryCapacity(MemTotalCGroup) + logutil.BgLogger().Info("use cgroup memory hook", zap.Int64("cgroupMemorySize", int64(cgroupValue)), zap.Int64("physicalMemorySize", int64(physicalValue))) + } else { + logutil.BgLogger().Info("use physical memory hook", zap.Int64("cgroupMemorySize", int64(cgroupValue)), zap.Int64("physicalMemorySize", int64(physicalValue))) + } + _, err = MemTotal() + terror.MustNil(err) + _, err = MemUsed() + terror.MustNil(err) +} + // InstanceMemUsed returns the memory usage of this TiDB server func InstanceMemUsed() (uint64, error) { used, t := serverMemUsage.get()