暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

备库cpu定时冲高的有趣案例

原创 xiongcc 2023-03-14
416

前言

今天一位同事找我处理了一个小案例,挺有趣,分享一下。公众号移步 备库cpu定时冲高的有趣案例

现象

同事反馈有一个远程备库 CPU 总是时不时得冲高一下,业务看了十分疑惑,明明备库没有承接任何的读业务,这个 CPU 为何还会冲高?

image20230308174145820.png

于是检查了一下备库的活动,主要是一些监控的 SQL,定时检测探活

image20230308174638636.png

所以矛头指向了这些监控 SQL。看下日志

[postgres@xiongcc ~]$ cat postgresql-03-08.csv | grep -A 1 'duration' | more 2023-03-08 17:12:09.012 CST,"dbmon","dbmgr",47375,"[local]",64085149.b90f,4,"SELECT",2023-03-08 17:11:37 CST,2/0,0,LOG,00000,"duration: 3226.495 ms statement: select 'pg_hostname:'||os_hostname();",,,,,,,,,,,"psql" ...

日志大致如上,我们的慢日志阈值配置是 1 秒,select 'pg_hostname:'||os_hostname()这条 SQL 就接近 3 秒,那去看下这个函数的定义

postgres=# \sf os_hostname CREATE OR REPLACE FUNCTION dbmgr.os_hostname() RETURNS text LANGUAGE plpythonu AS $function$ import os sys = os.name if sys == 'nt': hostname = os.getenv('computername') return hostname.strip() elif sys == 'posix': host = os.popen('echo $HOSTNAME') try: hostname = host.read() return hostname.strip() finally: host.close() else: return 'Unknown' $function$

函数很简单,顾名思义,就调用一下库获取主机名,os 就是提供了一些方便使用操作系统相关功能的函数来处理文件和目录。这么简单一个 SQL 为何耗费如此久的时间呢?调用一下看看

image20230308180448796.png

可以看到不定时就会冲高一下,并且可以看到时间全部在 startup,actual time 的 start-up 是从启动 executor 执行器直到扫描到符合条件的第一条结果为止,所以可以看到时间都花了"准备工作"上面。

既然这个函数涉及到了 os 库,与操作系统有关,那么又得回去看操作系统这个老朋友了,根据过往经验,感觉又是内存出问题了,于使用 sar -B 观察,

image20230308181023552.png

果然,又双叒叕是 direct memory reclaim,还是经典的内存回收图

Linux内核内存性能调优的一些笔记_技术杂谈_IT加油站

尽管 kswapd 异步线程是很努力的,但它毕竟是周期性执行的,难免出现某个时刻系统中剩余的内存极少,少到可能连回收内存操作本身需要的内存都不够了,当 free 内存降到了 min 水线以下,在某些情况下,比如,操作系统忽然需要通过伙伴系统为用户进程分配一大块内存,或者需要创建一个很大的缓冲区,而当时系统中的内存没有办法提供足够多的物理内存以满足这种内存请求,这时候,操作系统就必须尽快进行页面回收操作,以便释放出一些内存空间从而满足上述的内存请求,这种页面回收方式也被称作"直接页面回收",被阻塞进程的内存分配延迟就会提高,从而感受到卡顿,假如还不够,这时候只能使出终极武器了,那就是OOM killer,做法是选择一个进程(out_of_memory --> select_bad_process),然后kill掉(oom_kill_process中发送SIGKILL信号),把它占用的内存释放出来,牺牲了这个进程,保全了整个系统。虽然OOM killer有时候可能导致严重的损失,但总比系统完全崩溃要好。

可以看到这台主机是不是就在做直接内存回收,内存压力很大。为了验证想法,重新写一个函数

CREATE OR REPLACE FUNCTION exec_cmd2 (cmd text) RETURNS SETOF text AS $$ import os v = os.popen('ls ' + cmd) return v $$ LANGUAGE plpythonu;

很简单,根据参数打开某个目录的内容。此处打开 /tmp 目录模拟一下 👇🏻

image20230308183828513.png

轻松就复现出来了。

小结

既然知道了问题,还是那几样,调整内存回写策略/大页/NUMA/SWAP/主机内存碎片(/proc/buddyinfo)/调整 /proc/sys/vm/watermark_scale_factor水位线等优化措施。

数据库相比其他基础组件占据比较核心的位置,向上是各种应用的支撑引擎,向下调动计算、网络、存储等基础资源,数据库和软硬件息息相关,任何一环出现了一点风吹草动,数据库往往是第一个被拿出来放在砧板上被人鱼肉的

数据库到底行不行啊?怎么又变慢了?

数据库又抖动了,我的业务大量报错!

业务假如影响半小时,损失无法估量!

昨天业务还好好的,今天怎么就突然不行了?

就比如今天车管所交管APP就崩了,第一反应就是是不是又是数据库崩了?😂 多学学操作系统、网络和硬件等,准没错。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论