数据库运行过程经常会遇到进程由于操作系统内存不足导致进程无法 fork ,由于共享内存不足而导致SQL执行失败,由于操作系统内存不足导致数据库启动失败甚至引发OOM的问题。作为DBA,我们需要根据操作系统内存资源情况、数据库连接用户数量,合理的配置数据库运行内存相关参数。对于DBA来说,除合理配置数据库内存参数外,DBA还需会排查进程内存占用情况。以下详细介绍内存排查的相关命令。
一、确认总体内存使用情况
1、使用free 命令
我们看free命令结果的时候,不应该只关注free值,还应关注available。free是未使用过的物理内存,未被任何进程使用过的,而available是可提供数据库使用的内存总量。如果 free>available则认为free内存是可用内存,反之则认为available 是系统可用的空闲内存。buff/chche是可以被系统释放掉的缓存空间。如以下系统可用内存是 2625MB
[root@dbhost01 sa]# free -m
total used free shared buff/cache available
Mem: 3709 754 2154 101 801 2625
Swap: 3071 0 3071一般我们说 linux的可用内存都是指available内存,其实际包括free+可回收的buffer+cache内存。那实际应该保留多少free内存以及何时触发回收free内存呢?这里就需要引入linux的内存水位(watermark)概念了,内存水位由内核参数vm.min_free_kbytes来控制。
vm.min_free_kbytes默认值为67584,也被称作内存水位线,该值表示强制Linux VM最低保留多少空闲内存(Kbytes)。当Linux系统发现内存紧张时,系统就会通过一系列机制来回收内存,比如下面这三种方式:
- 回收缓存,比如使用 LRU(Least Recently Used)算法,回收最近使用最少的内存页面
- 交换分区,回收不常访问的内存,把不常用的内存通过swap out 到磁盘中
- 杀死进程,内存紧张时系统还会通过 OOM(Out of Memory),直接杀掉占用大量内存的进程。
2、查看 /proc/meminfo
cat /proc/meminfo可以更详细的看到OS的内存情况,以下几个关键值得注意。
- Dirty是FILE CACHE中尚未写入磁盘的脏数据,如果这个指标持续较高,那么说明OS的回写机制或者磁盘存在性能问题,需要检测磁盘写效率。
- PageTalbes 如果比较大,对于数据库来说,很可能是配置了较大的shared_buffers,而且没有启用HugePages,这时候hugepages的作用就凸显出来了。
- AnonHugePages 指标大于零说明没有关闭透明大页。
- CommitLimit:与 vm.overcommit_ratio 参数值有关,不管 vm.overcommit_memory 为何值。等于【CommitLimit = (Physical RAM * vm.overcommit_ratio / 100) + Swap】
- Committed_As:对应于sar -r 结果的 kbcommit列,表示满足当前的工作负载需要的虚拟内存(RAM + SWAP)
我们还需要关注的是 Swap 的使用率,如果free 内存很大,但是swap 使用率超过20%,很可能是OS的NUMA方面的配置不正确,没有全局分配内存。
二、排查进程占用内存
进程内存指标主要关注以下两个:
- VSS(Virtual Set Size):表示进程的虚拟内存大小,包括代码段、数据段、堆、共享库、映射文件等。VSS的值可能会很大,因为它包含了进程能够访问的所有虚拟地址空间。
- RSS(Resident Set Size):表示进程的常驻内存大小,即实际驻留在物理内存中的部分。RSS是进程当前使用的物理内存量,不包括共享库和映射文件等。将各进程的RSS值相加,通常会超出整个系统的内存消耗,这是因为RSS中每个进程都包含了各进程间共享的内存,因此存在重叠部分。
1、ps aux
ps命令可以获取进程的VSS、RSS、内存使用率,其中:
- VSZ 列表示的VSS,单位是KB
- RSS 列的单位是KB
- %MEM 列表示的是内存使用率,是进程RSS与系统总物理内存的比值
[v8r6c5b54@dbhost01 ~]$ ps aux | egrep "USER|kingbase"
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
v8r6c5b+ 7153 0.4 1.2 1545984 102504 ? Ss 16:16 0:00 /dbdata/v8r6c5b54/ES/V8/KESRealPro/V008R006C005B0054/Server/bin/kingbase
v8r6c5b+ 7154 0.0 0.0 336112 4932 ? Ss 16:16 0:00 kingbase: logger
v8r6c5b+ 7156 0.0 0.0 1545984 4796 ? Ss 16:16 0:00 kingbase: checkpointer
v8r6c5b+ 7157 0.0 0.1 1545984 10328 ? Ss 16:16 0:00 kingbase: background writer
v8r6c5b+ 7158 0.0 0.2 1545984 23152 ? Ss 16:16 0:00 kingbase: walwriter
v8r6c5b+ 7159 0.0 0.1 1546888 9712 ? Ss 16:16 0:00 kingbase: autovacuum launcher
v8r6c5b+ 7160 0.0 0.0 339088 5580 ? Ss 16:16 0:00 kingbase: stats collector
v8r6c5b+ 7161 0.0 0.0 1545984 4860 ? Ss 16:16 0:00 kingbase: ksh writer
v8r6c5b+ 7162 0.0 0.0 1546304 7136 ? Ss 16:16 0:00 kingbase: ksh collector
v8r6c5b+ 7163 0.0 0.0 1545984 4860 ? Ss 16:16 0:00 kingbase: kwr collector
v8r6c5b+ 7164 0.0 0.0 1546304 7124 ? Ss 16:16 0:00 kingbase: logical replication launcher
v8r6c5b+ 7196 0.0 0.0 221928 1064 pts/0 S+ 16:17 0:00 grep -E --color=auto USER|kingbase2、top
top命令可以获取进程的VSS、RSS,其中:
- VIRT 列表示的是VSS,单位是KB
- RES 列表示的是RSS,单位是KB
- SHR 表示共享内存段
通常 RES - SHR 表示进程消耗的内存
3、pmap
pmap命令可以获取进程的VSS,RSS,其中:
- Kbytes 列表示的VSS,单位是KB
- RSS 列表示的是RSS,单位是KB
4、查看进程状态文件
cat /proc/xxx/status , 通过查看进程的状态文件,可以获取进程的VSS、RSS,其中:- VmSize 表示的是VSS
- VmRSS 表示的是RSS
5、sar -r
结果类似如下:
02:19:05 PM kbmemfree kbavail kbmemused %memused kbbuffers kbcached kbcommit %commit kbactive kbinact kbdirty
02:19:06 PM 6592412 7030908 1335364 16.84 3352 561500 2298812 20.76 113944 786604 356
02:19:07 PM 6592412 7030908 1335364 16.84 3352 561500 2298812 20.76 113944 786660 356
02:19:08 PM 6592412 7030908 1335364 16.84 3352 561500 2298812 20.76 113944 786660 356
02:19:09 PM 6592272 7030768 1335504 16.85 3352 561540 2298812 20.76 113944 786660 396
各列意义如下:
- kbmemfree:空闲内存总量(RAM)
- kbavail:可用内存总量,包括 kbmemfree + kbinact 部分
- kbmemused:已使用的内存,但不包含操作系统内核自身使用的内存。
- kbcommit:满足当前的工作负载需要的虚拟内存(RAM + SWAP),当该值接近 CommitLimit 时,表示系统内存紧张。
- %commit:kbcommit/(RAM + SWAP)比值,而不是 kbcommit/CommitLimit ,所以,不能以该值超overcommit_ratio判定内存是否超分配 。
- kbactive:活跃的、不能被交换出去的内存(RAM)。
- kbinact:非活跃的内存。也就是需要时,可以被交换出去的内存。
三、关于OOM与内存无法分配问题
overcommit_memory 参数决定了是否允许内存的过量分配:
- 当为0的时候,当用户申请内存的时候,内核会去检查是否有这么大的内存空间。如果分配的内存超过空闲内存,则失败。
- 当为1的时候,内核始终认为,有足够大的内存空间,直到它用完了为止。也就是每次malloc 都成功,但会引起系统 OOM kill
- 当为2的时候,根据 【CommitLimit = (Physical RAM * vm.overcommit_ratio / 100) + Swap】 确定可分配的内存。 当 Committed_As 超过可分配内存时,内存分配会失败。
- 当overcommit_memory值为 1 时,容易触发OOM问题;而 overcommit_memory =2 时,可以避免OOM
- 当系统压力很大,内存不足时, overcommit_memory = 2 虽然不会导致OOM,但会导致进程无法分配到内存。对于数据库后台进程,如果无法分配到内存,进程也会异常退出,导致数据库宕机。
- 二者一个是操作系统主动OOM-kill(数据库绝对宕机),一个是内存不足被动退出的(数据库可能宕机)。




