网易首页 > 网易号 > 正文 申请入驻

故障分析 | 奇怪!内存明明够用,MySQL 却出现了 OOM

0
分享至

作者:刘开洋
爱可生交付服务部团队北京 DBA,主要负责处理 MySQL 的 troubleshooting 和我司自研数据库自动化管理平台 DMP 的日常运维问题,对数据库及周边技术有浓厚的学习兴趣,喜欢看书,追求技术。
本文来源:原创投稿
*爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。
问题

前几天遇到一个奇怪的问题,服务器内存明明够用,结果在对 MySQL 进行测压的时候却出现了 OOM,是 Linux 内核出错了吗?

具体现象如下:使用 sysbench 对 mysql 进行压测,并发 50、80 均正常输出,当并发达到 100 时开始报 OOM。

[root@yang-01 ~]# sysbench /usr/share/sysbench/oltp_read_write.lua --mysql-host=yang-02 --mysql-port=3306 --mysql-user=root --mysql-password=*** --mysql-db=test --table-size=100000 --tables=5 --threads=100 --db-ps-mode=disable --auto_inc=off --report-interval=3 --max-requests=0 --time=360 --percentile=95 --skip_trx=off --mysql-ignore-errors=6002,6004,4012,2013,4016,1062 --create_secondary=off run
sysbench 1.0.17 (using system LuaJIT 2.0.4)
Running the test with following options:
Number of threads: 100
Report intermediate results every 3 second(s)
Initializing random number generator from current time
Initializing worker threads...

FATAL: mysql_store_result() returned error 5(Out of memory (Needed 48944 bytes))
FATAL: 'thread_run' function failed: /usr/share/sysbench/oltp_common.lua:432: SQL error,errno = 5, state = 'HY000': Out of memory (Needed 48944 bytes)
FATAL: mysql_store_result() returned error 5(Out of memory (Needed 48944 bytes))
FATAL: 'thread_run' function failed: /usr/share/sysbench/oltp_common.lua:432: SQL error,errno = 5, state = 'HY000': Out of memory (Needed 48944 bytes)

MySQL 中 error log 的报错为:

······
2021-03-16T09:13:00.692622+08:00 343 [ERROR] [MY-010934] [Server] Out of memory (Needed 708628 bytes)
2021-03-16T09:13:00.692702+08:00 343 [ERROR] [MY-010934] [Server] Out of memory; check if mysqld or some other process uses all available memory; if not, you may have to use 'ulimit' to allow mysqld to use more memory or you can add more swap space
2021-03-16T09:13:59.832037+08:00 374 [ERROR] [MY-000000] [InnoDB] InnoDB: Assertion failure: ut0ut.cc:678:!m_fatal
InnoDB: thread 140375101384448
InnoDB: We intentionally generate a memory trap.
InnoDB: Submit a detailed bug report to http://bugs.mysql.com.
InnoDB: If you get repeated assertion failures or crashes, even
InnoDB: immediately after the mysqld startup, there may be
InnoDB: corruption in the InnoDB tablespace. Please refer to
InnoDB: http://dev.mysql.com/doc/refman/8.0/en/forcing-innodb-recovery.html
InnoDB: about forcing recovery.
01:13:59 UTC - mysqld got signal 6 ;

分析

对 MySQL OOM 我们一步步进行分析,首先应该查看 ulimit 限制,

[root@yang-02 ~]# ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 23045
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 23045
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited

系统并没有对 ulimit 进行限制,100 个并发量连接在我们的配置之内,那就不是 ulimit 配置的问题,接下来分析下内存的使用情况,

在复现 MySQL OOM 的过程中,查看对应内存使用,通过 top 和 free 命令进行监控,得到以下信息,

[root@yang-02 ~]# free -m
total used free shared buff/cache available
Mem: 16047 1958 8956 8 5132 13920
Swap: 5119 0 5119
[root@yang-02 ~]# top
top - 17:21:30 up 32 min, 4 users, load average: 0.00, 0.04, 0.11
Tasks: 226 total, 2 running, 224 sleeping, 0 stopped, 0 zombie
%Cpu(s): 2.2 us, 0.6 sy, 0.0 ni, 97.2 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 16432236 total, 9164596 free, 2012156 used, 5255484 buff/cache
KiB Swap: 5242876 total, 5242876 free, 0 used. 14247508 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
7654 root 20 0 13.7g 1.7g 14312 S 1.3 10.3 0:00.27 mysqld

这里看我们的内存使用很正常,free 和 available 都很多,swap 都没有使用,唯一存在异常的是虚拟内存有点高,我们接着分析:

进一步查看一下 /proc/meminfo,具体分析一下内存的使用情况,其中以下两个参数引起了注意:

[root@yang-02 ~]# cat /proc/meminfo | grep Commit
CommitLimit: 13458992 kB
Committed_AS: 13244484 kB

一般来说 CommitLimit 的值是要比 Committed_AS 的值要小的,结合现在内存的使用,我们应该注意到一个 OS kernel 参数

[root@yang-02 ~]# cat /etc/sysctl.conf |grep vm.overcommit_memory
vm.overcommit_memory=2

将 vm.overcommit_memory 调整为0,压测时 MySQL OOM 消失了。

这三个参数值是什么意思呢?它和我的内存使用的关系是什么?内存真的够用吗?通过翻看 Linux 的内核文档我们来进行详细说明。

分析 vm.overcommit_memory 的使用

首先解释下什么叫 overcommit,overcommit 的意思是指操作系统承诺给进程的内存大小超过了实际可用的内存。

从内核版本 2.5.30 开始,这个参数的三种取值分别为:

overcommit_memory:This value contains a flag that enables memory overcommitment.

  • • When this flag is 0, Heuristic overcommit handling, the kernel attempts to estimate the amount of free memory left when userspace requests more memory. Obvious overcommits of address space are refused. Used for a typical system. It ensures a seriously wild allocation fails while allowing overcommit to reduce swap usage. root is allowed to allocate slightly more memory in this mode. This is the default.

  • • When this flag is 1, Always overcommit, the kernel pretends there is always enough memory until it actually runs out. Appropriate for some scientific applications. Classic example is code using sparse arrays and just relying on the virtual memory consisting almost entirely of zero pages.

  • • When this flag is 2, Don't overcommit, the kernel uses a "never overcommit" policy that attempts to prevent any overcommit of memory. The total address space commit for the system is not permitted to exceed swap + a configurable amount (default is 50%) of physical RAM. Depending on the amount you use, in most situations this means a process will not be killed while accessing pages but will receive errors on memory allocation as appropriate.

中文释义:

  • • 当这个标志为 0 时,表示试探性的 overcommit,当用户空间请求更多内存时,OS kernel 会预估剩余的空闲内存量,如果内存申请特别大就会被拒绝。例如 malloc() 一次性申请的内存大小就超过了 swap 和 physical RAM 的和,就会遭到 kernel 拒绝overcommit。

  • • 当这个标志为 1 时,kernel 会假装一直有足够的内存,直到实际用完为止。

  • • 当这个标志为 2 时,kernel 使用“永不过度提交”的策略,试图阻止任何内存的过度提交。

从含义中分析,如果我们将 vm.overcommit_memory 的值设为 2,就很有可能出现内存申请的值超过我们的阈值,就会受到禁止。

该阈值是通过内核参数 vm.overcommit_ratio 或 vm.overcommit_kbytes 间接设置的,从对应参数解释中得到公式如下:

CommitLimit = Physical RAM * vm.overcommit_ratio + Swap // vm.overcommit_ratio 是内核参数,默认值是 50,表示物理内存的 50%。

测试环境中 Physical RAM 的值约为 16G,Swap 的值约为 5G,计算下来可正对应 CommitLimit 的值 13 个 G。

/proc/meminfo 中的 Committed_AS 表示所有进程已经申请的内存总大小,而我们查询的 free 和 top 下的内存则是进程已经分配的内存。

Committed_AS 是 OS kernel 对所有进程在最坏情况下需要多少 RAM/swap 的预估,才能保证工作负载不会出现 OOM(内存不足),因此会存在过度申请提交内存的现象。

这个值是系统所有运行的程序所申请的内存大小,并不代表着分配使用的大小,而且各个程序申请的内存是可共享的。

虽然 Committed_AS 的数值与虚拟内存 VIRT 的大小很相似,目前没有找到官方说明他们之间的联系,但经过多次测试,它的大小和虚拟内存并没有关系。

总结

如果 Committed_AS 超过 CommitLimit 就表示发生了overcommit,超出越多表示 overcommit 越严重,kernel 的 killer 会挑一部分进程干掉,如果内存不够还会继续被 killer 干掉,MySQL 在内存占用中属于大头,首当其冲。

测试环境查看 Committed_AS 和 CommitLimit 的参数值为:

[root@yang-02 ~]# cat /proc/meminfo | grep Commit
CommitLimit: 13458992 kB
Committed_AS: 13244484 kB

两者已经十分接近,非常容易发生 MySQL 的 OOM,因此需要调整的是增加内存或者将 vm.overcommit_memory 的值设为 0/1,具体需要根据环境变更。

附:还有两个参数与我们这次的内存分配有关系,不过影响不大,有兴趣的同学可以自行谷歌:admin_reserve_kbytes 和 user_reserve_kbytes。

参考:
https://www.kernel.org/doc/Documentation/vm/overcommit-accounting
https://www.kernel.org/doc/Documentation/sysctl/vm.txt
http://lwn.net/Articles/28345/
https://www.win.tue.nl/~aeb/linux/lk/lk-9.html#ss9.6

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
86岁老人随口乱说代号,儿子上报后,国安领导:马上接通中央部委

86岁老人随口乱说代号,儿子上报后,国安领导:马上接通中央部委

知鉴明史
2025-10-23 14:01:49
高市拒绝撤回谬论,不到48小时,中方深切哀悼,日本重要人物逝世

高市拒绝撤回谬论,不到48小时,中方深切哀悼,日本重要人物逝世

博览历史
2025-11-12 16:50:23
9分钟爆砍28分,命中率100%,中国篮球迎来超级新星,她太强了

9分钟爆砍28分,命中率100%,中国篮球迎来超级新星,她太强了

篮球专区
2025-11-11 22:33:00
俄方给中国提了醒:要想拿下台岛,必须摧毁美军的西太平洋基地!

俄方给中国提了醒:要想拿下台岛,必须摧毁美军的西太平洋基地!

大国纪录
2025-11-12 09:48:25
国足VS越南,12名主力缺席,安东尼奥斯拿什么取胜,看看首发阵容

国足VS越南,12名主力缺席,安东尼奥斯拿什么取胜,看看首发阵容

金风说
2025-11-12 16:10:50
广东首节险胜浙江!仅靠王睿泽,小胡+赵睿+内线迷失,朱俊龙暴走

广东首节险胜浙江!仅靠王睿泽,小胡+赵睿+内线迷失,朱俊龙暴走

篮球资讯达人
2025-11-12 19:57:29
茼蒿立大功!医生调查发现:茼蒿对这5种疾病有好处,建议常吃

茼蒿立大功!医生调查发现:茼蒿对这5种疾病有好处,建议常吃

阿纂看事
2025-10-13 15:36:03
突发大火!南朝四百八十寺中的永庆寺成永恒,11天前举办消防演练

突发大火!南朝四百八十寺中的永庆寺成永恒,11天前举办消防演练

火山诗话
2025-11-12 17:40:28
赵露思生日音乐会造型封神!又纯又欲氛围感拉满

赵露思生日音乐会造型封神!又纯又欲氛围感拉满

述家娱记
2025-11-09 19:00:42
孙颖莎险胜陈梦,人气与实力并存,精彩对决!

孙颖莎险胜陈梦,人气与实力并存,精彩对决!

又是美好的日子
2025-11-12 14:38:58
一家中餐馆在哈兰德光顾后推出同名套餐,包含烧鸭、叉烧及脆皮烧肉

一家中餐馆在哈兰德光顾后推出同名套餐,包含烧鸭、叉烧及脆皮烧肉

懂球帝
2025-11-12 16:05:06
相当于20个三峡大坝?外媒已经发现,中国悄悄在沙漠里干了件大事

相当于20个三峡大坝?外媒已经发现,中国悄悄在沙漠里干了件大事

毒sir财经
2025-11-11 20:31:06
微软AI部门CEO推行严格线下办公政策:每周至少到办公室四天

微软AI部门CEO推行严格线下办公政策:每周至少到办公室四天

IT之家
2025-11-12 19:25:02
养了三个月女儿,出院竟成“男婴”,父母心理受重创

养了三个月女儿,出院竟成“男婴”,父母心理受重创

陆弃
2025-11-11 14:57:14
迪拜富人来中国旅游,回国一天后坦言:阿联酋跟中国差距天差地别

迪拜富人来中国旅游,回国一天后坦言:阿联酋跟中国差距天差地别

户外钓鱼哥阿勇
2025-11-11 06:16:51
刚发生的这件事情,动摇了霸权的根本,是一次迎头暴击

刚发生的这件事情,动摇了霸权的根本,是一次迎头暴击

一个坏土豆
2025-11-11 20:07:10
俄军大部队开入红军城

俄军大部队开入红军城

鲁中晨报
2025-11-12 19:55:06
为什么要坚定加入CPTPP呢?因为WTO组织已经被玩坏了……

为什么要坚定加入CPTPP呢?因为WTO组织已经被玩坏了……

翻开历史和现实
2025-11-07 14:42:30
张家界七星山荒野求生选手体检结果出炉,5名选手血钾超标,3天后复查

张家界七星山荒野求生选手体检结果出炉,5名选手血钾超标,3天后复查

极目新闻
2025-11-11 20:09:43
不办葬礼、减少“麻烦”,越来越多日本人选择“直葬”

不办葬礼、减少“麻烦”,越来越多日本人选择“直葬”

参考消息
2025-11-11 19:06:31
2025-11-12 21:04:49
爱可生云数据库
爱可生云数据库
企业数据处理技术整体解决方案
411文章数 20关注度
往期回顾 全部

科技要闻

前阿里人亲述: “经济上行”期双11什么样

头条要闻

1家5口被邻居杀害:3岁孩子都没放过 行凶全程仅2分钟

头条要闻

1家5口被邻居杀害:3岁孩子都没放过 行凶全程仅2分钟

体育要闻

消磨你上千小时的足球游戏,走过第20年

娱乐要闻

再王珞丹和白百何 明白两人"差别"在哪

财经要闻

段永平最新访谈:聊企业经营 投资理念

汽车要闻

7座皆独立座椅/新增5座版 体验第三代吉利豪越L

态度原创

本地
艺术
旅游
时尚
公开课

本地新闻

云游安徽 | 凌滩玉魄淬千年,诗意钢城马鞍山

艺术要闻

毛主席珍贵签名照曝光,鲜为人知的历史瞬间!

旅游要闻

环两山引领区广州片区吃喝玩乐游购全攻略宝藏电子地图发布

“廓形穿衣法”太火了!掌握这5个法则让你美一整个冬天

公开课

李玫瑾:为什么性格比能力更重要?

无障碍浏览 进入关怀版