glibc缺陷居然会导致MySQL卡住?

news2024/11/25 19:44:48

问题来源:

版本:5.7.25。

现象:备机主从延迟不断变大,无法登陆数据库,建立连接时卡住,但很快恢复正常了。

分析:

常规分析:

        通常情况下,这类问题无法分析,来的快去的快,日志中不会记录太多有效信息,但这次DBA同学在数据库hang住时把数据库运行堆栈打印保存了,这就有了分析根因的可能性。

        查看error log在hang住时间节点附近没有有效信息,慢查询记录也为空,查看监控发现当时写入insert非常高,这是slave机,写入来源于SQL线程回放,io利用率当时也跑满,但cpu也比较高,内存使用量在事发前后没有变化。如果简单的把这个故障归结到写入压力大,io资源不够,很难说的过去,压力大主从延迟变大可以理解,但是无法登陆数据库就不能解释了。

MySQL堆栈分析:

        由于有堆栈,进一步分析当时堆栈,整理如下:

         当时已经累积有753个尝试建立的连接的线程被卡住无法登陆,其它除sql线程外,都无明显异常。

        从堆栈上看,sql线程正在对一个分区表做insert数据,当时正在做内存申请操作,这就是比较诡异了,内存申请通常来说都是纳秒微秒级能完成的任务,这里居然能被打印出来,显然这个动作卡的时间比较长。

        查看一下内存使用率,当前MySQL进程居然占用了90%的内存,注意这是现在非故障时,现在没有业务流量,仅有几个复制线程在跑,而故障时作为读库有大量业务连接,内存占用量肯定更高。

        此时立马有个问题浮现:为什么mysqld进程没有OOM?查看一下规格,64c128G,如此强悍的机器,故障时还有富余内存,不至于OOM,但是这个内存使用率必然导致数据库进程在生死边缘挣扎了,同时也能解释为什么会卡在申请内存这了。

linux系统内存将耗尽时,大概会采取以下措施:

(1)系统内核会尝试通过回收不用的内存页(page)来为该进程分配内存。

(2)如果回收内存页后仍无法满足该进程的内存需求,Linux 内核会尝试通过交换空间(swap)来腾出更多的物理内存。

(3)如果交换空间不足以满足该进程的内存需求,Linux 内核会选择杀死某些进程来释放物理内存。

        数据库进程此时就处在第1-2阶段,而本机内存又比较大,操作系统进行这个过程可能比较慢,导致申请内存的线程一直在等,同样建立连接的线程也全需要申请内存,自然无法成功建立,但总体上运气不错,没有走到第3阶段就恢复了,mysqld没有被系统kill。

MySQL为什么会占如此多内存

        至此基本上确定了是内存不够,系统重分配慢所至,似乎可以至此为止了,但是这样的结论没有什么实际用处,下次业务高峰照样发生故障,所以有必要继续分析内存哪去了,是否可以避免再次故障。

那么内存去哪了?

  • buffer_pool 64G,减掉64G仍然有五六十G。

  • 当前没有业务连接,thread_pool_size才64,不会缓存太多线程,顶天不会超过1G。

  • table_open_cache、table_definition_cache 参数配的8192,看了下data目录,好家伙,3.9TB,并且全是分区表,9万多个ibd文件,那么这些表的缓存文件会占不少内存,可能会占到几个G。

  • 再加上其它一些其它内存,所有这些额外内存估计最多能占10多G,加上buffer pool内存后,总的往多算也就七八十GB。而当前没有业务连接的情况下,占用90%*128GB=115G,显然是不正常的。

难道是MySQL的内存泄漏bug?

        MySQL 5.1、5.5时代是存在一些内存泄漏bug的,但5.6开始极少了,5.7更是少之又少,目前没遇到过被证实的MySQL5.7内存泄漏bug。看再这个实例运行时间:900多天,要是mysqld本身有泄漏很难坚持这么久的。

         那么内存到底去哪了?直接给结论,这是glibc默认内存分配库ptmalloc的缺陷,有大量内存碎片无法被利用,导致进程内存使用量越来越大。那么是如何认定是该问题的?直接调gdb释放内存碎片命令看结果认定。

        直接执行:gdb -p 1793 -batch -ex 'call malloc_trim(0)'

        1793为mysqld进程,执行时可能会卡一两秒,但无其它影响,malloc_trim是专门用来释放内存碎片的,执行完之后内存占用情况:

 内存使用量瞬间从90%掉到62.5%,回到健康状态。

        该问题多年前首次在MySQL上遇到时,全过程花了数月才定位到,因为这个碎片内存涨的非常慢,导致定位分析周期长,像本次的案例就用了900多天才涨到这个量。

ptmalloc库缺陷介绍

        ptmalloc的这个缺陷也简单介绍下,不光MySQL,所有的用glibc内存库的c/c++程序都可能遇到,尤其多线程高并发长期运行的服务程序,一定有内存碎片,只是多少的区别。

        为了提高多线程并发情况下的内存分配效率,glibc 的ptmalloc维护了多个内存管理单元,每一个称作一个 arena,每个arena都使用 malloc_state来描述(malloc_state主要用于维护空闲的chunk 链表),只有main_arena 是通过 sbrk 来获得和管理内存的,其他arena是通过mmap 获取的;arena 可以包含多个heap,每个heap是通过mmap 获取的一个线性区,heap的最大大小是HEAP_MAX_SIZE(在64位系统是64M)。

        分配内存时,按照TLS(线程私有数据)中的arena –>main_arena ->arena1 ->arena2->… 的顺序进行遍历,依次进行trylock,如果 trylock成功,则在对应的arena中分配内存,若都不成功新建一个arena 来分配。

        当进程长期运行时,一个大内存块被不断被拆分成小碎片,这些小碎片内存会越来越多,也越来越难被重用,导致“内存泄漏”。

        另一方面,glibc的多线程运行也会带来一些问题,假设当前有3个arena,进程需要20kb内存,当前3个arena都有20kb的内存块,但是这些个arena都在使用中,try_lock加不上锁,此时进程就会增加一个arena来分配内存。同样假如arena2有符合要求的20kb内存块,但在arena1上try_lock成功,arena1又没有20kb的内存块,就会直接新分配一块挂在arena1上。总的来说,多线程下,存在原来的内存碎片无法利用反而去申请新的arena或者 heap的情况,导致内存碎片越来越多。

        想了解详细的可以找下相关glibc内存库相关的资料进行研究分析,参考文档:glibc内存管理ptmalloc源代码分析

总结与建议

  •  ptmalloc在多线程并发的情况下,容易产生内存碎片,日积月累容易占用大量不可利用内存,等同于内存泄露。

  • malloc_trim可以回收空闲碎片内存,对于长期内存高水位实例,可以定期(如按月)在业务低谷时执行。

  • 可以考虑更换mysql内存分配库,事实上,国内公有云mysql基本都用jemalloc代替了ptmalloc,除了能避免内存碎片问题,它的性能也好很多。

  • 另外,这个实例单库3.9T,近10万个数据文件,可以考虑优化一下空间。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/724830.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vmware17安装openkylin

官网 系统下载-openKylin 开放麒麟社区官网 | 开源聚力,共创未来 下载链接 https://www.openkylin.top/downloads/download-smp.php?id18 安装 点击浏览,选择镜像 修改服务器cpu配置 修改内存配置 修改网络连接方式 点击启动 等待安装完成 出现上图说…

比较两个Excel表格中的数据,不相同的高亮显示

下面是常用的在Excel中比较两个Excel表格数据的方法, 比如要比较下面A和B中的数据是否一致: 可以这样做:

ikbc键盘2.4G接收器丢失,重新对码

我的键盘:ikbc W200 1.键盘关掉重开; 2.新接收器插在电脑上; 3.电脑上打开软件,点开始对码,一会就连接上了。 对码软件放在这里: 我用夸克网盘分享了「IKBC 对码.rar」,点击链接即可保存。打开…

(Qt) Http之Get请求使用基础

文章目录 前言Code完整code效果循环loop的使用 讲解配置相关对象Https END 前言 http的操作是网络通信中非常常见的操作,其中广泛使用get,post两种操作。 本文将对Qt中,http的get请求做简单应用,来进行展示。 Code 完整code …

2分钟完成Github配置ssh密钥

2分钟完成Github配置ssh密钥 前言: 配置ssh密钥的目的是为了可以在自己的本地开发环境顺利拉取和推送代码到Github 本机是Ubuntu 16.04环境,已安装ssh 步骤1 进入当前用户的home目录: #执行以下命令进入 cd ~进入.ssh/目录下生成ssh的密钥…

JS antdv实现表格树形级联效果

概述 项目中需实现以下这种效果:级联数据,表格横向排列,数据之间相互联动。现有UI组件无法满足此需求,只能撸起袖子加油干!! 实现效果如下 开发前先准备一个树形数据 treeData.js const treeData [{ar…

Linux常用命令【多图预警】

Linux常用命令 文章目录 Linux常用命令Linux虚拟机的安装Linux系统目录结构Linux命令的语法基础命令查看当前目录下所有子目录和子文件ls查看命令手册man查看当前目录pwd切换到指定目录cd 管道符 |文件目录操作命令创建一级目录(文件夹)mkdir创建多级目录…

计算机毕业论文内容参考|基于微信小程序的学生课表系统的设计与实现

文章目录 导文摘要前言绪论1课题背景2国内外现状与趋势3课题内容相关技术与方法介绍系统分析系统设计系统实现系统测试总结与展望1本文总结2后续工作展望导文 计算机毕业论文内容参考|基于微信小程序的学生课表系统的设计与实现 摘要 基于微信小程序的学生课表系统是一个方便学…

【电路原理学习笔记】第2章:电压、电流和电阻:2.8 电气安全

第2章:电压、电流和电阻 2.8 电气安全 2.8.1 触电 电流(而非电压)通过人的身体是触电的的原因。当然,需要有电压施加在有电阻的物体上才能产生电流。当人身体上的一个点与电压接触,而另一个点与不同的电压或地面接触…

玄子Share - mybatis-Plus 3.5.3.1 学习笔记

玄子Share - mybatis-Plus 3.5.3.1 学习笔记 介绍 MyBatis-Plus (opens new window)(简称 MP)是一个 [MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。 愿景:…

docker 镜像的使用与创建(三)

相关文章: linux上docker容器运行web应用简单介绍(二)_做测试的喵酱的博客-CSDN博客 linux docker安装及报错处理_做测试的喵酱的博客-CSDN博客 Docker 容器使用 | 菜鸟教程 linux应用docker基本使用(一)_做测试的喵酱的博客-…

29. 求出商品连续售卖的时间区间

文章目录 题目需求思路一实现一题目来源 题目需求 从订单详情表(order_detail)中,求出商品连续售卖的时间区间。 期望结果如下: sku_id (商品id)start_date (起始时间)end_date &…

鸢尾花书简介

鸢尾花书简介 鸢尾花书 系列介绍1《编程不难》2《可视之美》3《数学要素》4《矩阵力量》5《统计至简》6《数据有道》7《机器学习》 重要链接 特别棒,极力推荐!!! 鸢尾花书 系列介绍 1《编程不难》 《编程不难》:https:…

win11预览版更新,并尝试使用Copilot

文章目录 win11预览版更新,并使用Copilot先说结果所需内容具体操作更新操作系统版本更新Edge安装ViVeTool v0.3.3 测试Copilot问题唯一优点 总结 win11预览版更新,并使用Copilot 先说结果 体验一言难尽,就相当于是一个快捷聊天提问窗口。 自…

C语言实现WiFi数据收发(电脑作为服务器)

功能实现: 手机与电脑在一个局域网,实现手机与电脑之间数据收发。 主要是用socket协议完成功能。 电脑作为服务器,手机作为客户端 编程环境: 电脑端变成环境:VC6.0 手机端WiFi助手: 核心代码: …

K8S平台应用安全(Secret Service Ingress)

平台应用安全 1 平台应用安全1.1 敏感数据1.1.1 应用数据1.1.2 Secret基础1.1.3 Secret案例11.1.4 Secret案例2 1.2 数据访问1.2.1 网络体系解读1.2.2 Service实践1.2.3 Service进阶1.2.4 Service解读 1.3 应用流量1.3.1 Ingress基础1.3.2 Ingress实践1.3.3 Ingress进阶1.3.4 I…

用Python实现黑客代码

前言 用Python实现黑客代码,根本关不掉的窗口 📝个人主页→数据挖掘博主ZTLJQ的主页 个人推荐python学习系列: ☄️爬虫JS逆向系列专栏 - 爬虫逆向教学 ☄️python系列专栏 - 从零开始学python 首先先介绍一下使用到的tkinter库 Tkinter 是 P…

通付盾联合嘶吼安全产业研究院共同发布《数据安全细分市场调研报告》并成功入选数据安全产业图谱多项细分领域,附报告!

7月4日,通付盾联合嘶吼安全产业研究院共同发布《时维鹰扬履践致远:数据安全细分市场调研报告2023》。 百炼露锋芒,本次《时维鹰扬履践致远:数据安全细分市场调研报告2023》聚焦数据安全市场细分领域市场规模、厂商玩法和产品竞争情…

二十三种设计模式第十四篇--策略模式

策略模式:主要围绕一个类的行为或者其算法在运行时更改,也是一种行为型模式。 在软件开发中,我们经常遇到需要根据不同的情况选择不同算法或行为的情况。传统的做法是使用大量的条件语句来实现这种逻辑,但这样的实现方式往往难以…

Numpy学习(参考)

目录 一、前言 二、numpy官方文档 文档划分 参数规范 相关知识明知 Routines学习(部分) 1、创建 2、数组操作常用 ufunc 三、numpy基本操作 开篇探索 数据类型 创建数组 创建数组有5种常规机制 常用创建方法 拷贝创建 数组运算 形状操作 查看形状 形状变换 …