diff --git a/tidb-server/main.go b/tidb-server/main.go index d8b830fc9c9a1..80bcf40392b6c 100644 --- a/tidb-server/main.go +++ b/tidb-server/main.go @@ -197,6 +197,7 @@ func main() { checkTempStorageQuota() } setupLog() + memory.InitMemoryHook() setupExtensions() err := cpuprofile.StartCPUProfiler() diff --git a/util/memory/meminfo.go b/util/memory/meminfo.go index 4db9ac67b07dc..249377475df22 100644 --- a/util/memory/meminfo.go +++ b/util/memory/meminfo.go @@ -21,8 +21,10 @@ import ( "github.com/pingcap/failpoint" "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/util/cgroup" + "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tidb/util/mathutil" "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 v.Total, 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 @@ -162,6 +169,36 @@ 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 + 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()