记录一次现网MySQL内存增长超限问题定位过程
问题现象
现网物理机内存近几日内爆涨使用率超过了90%,可用内存从250G,降低到20G以下,报告警。
服务器使用情况来看,并没有什么异常。除了QPS缓慢增长外。

MySQL内存分配结构
定位这个问题,先了解一下MySQL的内存分配知识。
MySQL的内存分配分为两部分,一部分是启动之初就分配的,主要是buffer_pool_size,key_buffer_size(本例256M)等。
还有一部分是每个连接建立并执行查询等操作时分配的。
https://dev.mysql.com/doc/refman/5.6/en/memory-use.html
MySQL的内存分配分为两部分,一部分是启动之初就分配的,主要是buffer_pool_size,key_buffer_size(本例256M)等。
还有一部分是每个连接建立并执行查询等操作时分配的。
https://dev.mysql.com/doc/refman/5.6/en/memory-use.html
每个连接分配的(当有相应的SQL操作时,非活动线程占用的内存很小)
(read_buffer_size+read_rnd_buffer_size+sort_buffer_size+thread_stack+
        join_buffer_size+binlog_cache_size)=8M+32M+8M+256K+2M+32K~=51M
但是,需要注意的是,每个连接。有需要的时候会动态的扩展到max_allowed_packet,也即64M。也许这就是文件中很多64M的内存块分配的原因吧?
我猜想是这样,但是实际上确不太正确。因为Threads_connected | 75, Threads_created | 622,状态信息显示所有的连接创建数总共才622个,而且按文档所述连接所用的内存应该主要按照活动的连接进程来计算。 现网即时状态显示,活动连接总计才 Threads_running | 3 个。
max_allowed_packet = 64M
Each thread that the server uses to manage client connections requires some thread-specific space. The following list indicates these and which system variables control their size:
A stack (thread_stack)
A connection buffer (net_buffer_length)
A result buffer (net_buffer_length)
The connection buffer and result buffer each begin with a size equal to net_buffer_length bytes, but are dynamically enlarged up to max_allowed_packet bytes as needed. The result buffer shrinks to net_buffer_length bytes after each SQL statement. While a statement is running, a copy of the current statement string is also allocated.
When a thread is no longer needed, the memory allocated to it is released and returned to the system unless the thread goes back into the thread cache. In that case, the memory remains allocated.
注:还有上面所述的关于read_buffer_size, read_rnd_buffer_size
根据我的经验最大只能配置2M左右。太大了,非但不会提升性能,还会影响性能。
至于原因,记得是在某篇文章里面提到过。不太记得出处在哪了,等我找到了再更新。
但这个参数,我是不打算改了。因为是现网,还有这是客户系统,就算有再充分的原因,没有严重问题也不可能接受你的建议修改的。
用PMAP查看内存具体分配
除了Buffer pool预先分配的内存230G是在已知的情况下。
内存PMAP统计信息显示其中有1659个64M=104G的内存块分配。
问题应该就是出在这里,到底是什么导致很多不同的64M的内存块分配,而且分配后还没有释放?

下一步对策
从前面的分析来看,没有任何一点能解释问题发生的根本原因。
我猜测问题有可能是内存泄露,也许是内存未释放。
那接下来,我们该怎么办呢?目前来看,我几乎没有办法。
内存问题的定位工具,由于现网无法使用。
Valgrind
其实还可以查询一下performance_schema关于内存的统计信息。
但可惜这个是5.7之后的版本才有的功能。现网5.6版本不支持。
最后的办法:
1)在实验室搭建一个和现网一样的环境(数据一样)。但没有流量数据,可能也难以复现问题。
2)升级到5.7,反正早晚都要升级的。升级后,关于内存这一块就可以查看更多的信息了。
注:关于内存不释放我也怀疑过有可能是OS的问题,比如说solaris系统就是如此(属于solaris系统的正常现象)。
https://bugs.mysql.com/bug.php?id=77616
Solaris系统下,当内存被进程主动释放时,OS不会回收内存到OS,只会标记内存为未使用,等下次进程再需要时再指配给进程,这就是所谓内存重用。表向为进程占用内存一直维持高位不会下降。
而Redhat, centos是会把内存回收给OS,表向为进程占用内存下将。现网的机器是centos核的,应该不会有此问题。
MySQL 5.7 performance_schema 内存查询


其它检查项
检查是否有使用内存表,结果是没有(因为只有系统虚内存表)
select * from information_schema.tables where engine='MEMORY‘
检查performance_schema占用内存,结果显示为约为761M
SHOW ENGINE PERFORMANCE_SCHEMA STATUS
Type: performance_schema
  Name: performance_schema.memory
Status: 798686336
167 rows in set (0.00 sec)
白高兴
突然有同事告诉我,现网还大量使用了存储过程。这个是我之前忽略的一点。
我一查,是不是有存储过程的Memory leak的BUG?
结果真有。我兴冲冲的用测试机器测试了一下,结果是死活不出现我所期待的现象。
再一查,这个BUG,居然在目前使用的版本之前已经修复了。
https://bugs.mysql.com/bug.php?id=76349
后续
问题定位两天无果。隔了一个周末来看,居然告诉我系统被Monitor重启了,问题没了。
只能等待下次出现问题再说了。
虽然没有定位出问题,但过程也还是很有参考意义的。
问题天天有,世界照样转。不说了,得去别的地方搬砖了。
记录一次现网MySQL内存增长超限问题定位过程的更多相关文章
- 【MySql】赶集网mysql开发36条军规
		
[MySql]赶集网mysql开发36条军规 2012-05-14 14:02:33 分类: Linux 写在前面的话: 总是在灾难发生后,才想起容灾的重要性: 总是在吃过亏后,才记得曾经有人提醒 ...
 - [赶集网] 【MySql】赶集网mysql开发36条军规
		
[赶集网] [MySql]赶集网mysql开发36条军规 (一)核心军规(1)不在数据库做运算 cpu计算务必移至业务层:(2)控制单表数据量 int型不超过1000w,含char则不超过50 ...
 - 赶集网mysql开发36军规
		
赶集网mysql开发36军规 写在前面的话: 总是在灾难发生后,才想起容灾的重要性: 总是在吃过亏后,才记得曾经有人提醒过. (一)核心军规 (1)不在数据库做运算:cpu计算务必移至业务层 (2)控 ...
 - 线上mysql内存持续增长直至内存溢出被killed分析(已解决)
		
来新公司前,领导就说了,线上生产环境Mysql库经常会发生日间内存爆掉被killed的情况,结果来到这第一天,第一件事就是要根据线上服务器配置优化配置,同时必须找出现在mysql内存持续增加爆掉的原因 ...
 - MySQL内存体系架构及参数总结 ---图解
		
http://www.cnblogs.com/kissdb/p/4009614.html 内存结构: Mysql 内存分配规则是:用多少给多少,最高到配置的值,不是立即分配 图只做大概参考 全局缓存包 ...
 - 18、MySQL内存体系架构及参数总结
		
内存结构: Mysql 内存分配规则是:用多少给多少,最高到配置的值,不是立即分配 图只做大概参考 全局缓存包括: global buffer(全局内存分配总和) = innodb_buffer ...
 - MySQL内存调优
		
原文链接: MySQL Memory Allocation -- by Rick James原文日期: Created 2010; Refreshed Oct, 2012, Jan, 2014 翻译人 ...
 - MySQL -- 内存使用监控详解
		
问题: 1.我们怎么确定MySQL的各个部分分别使用了多少内存? 2.当有MySQL由于内存泄露引起OOM时.我们怎么提前发现? 怎么监控MySQL内存使用: 答案是通过performance_sch ...
 - mysql内存参数整理和条调优以及内存统计
		
date:20140530auth:Jin 参考:http://dev.mysql.com/doc/refman/5.5/en/server-status-variables.html#http:// ...
 
随机推荐
- ES6中的Generator函数
			
今天小编发现一个es6中的新概念,同时也接触到了一个新关键字yeild,下面我就简单和大家聊聊es6中的generator函数.大家还可以关注我的微信公众号,蜗牛全栈. 一.函数声明:在functio ...
 - springboot bean的循环依赖实现 源码分析
			
springboot bean的循环依赖实现 源码分析 本文基于springboot版本2.5.1 <parent> <groupId>org.springframework. ...
 - 循序渐进BootstrapVue,开发公司门户网站(5)--- 使用实际数据接口代替本地Mock数据
			
在我们开发一些门户网站功能的时候,有时候我们需要快速的创建数据模型来进行数据展示,因为数据结构可能处于不断的修正变化之中,因此服务端的接口我们可以暂时不开发,当我们基本完成数据结构和界面展示的时候,就 ...
 - 2、SpringBoot整合之SpringBoot整合servlet
			
SpringBoot整合servlet 一.创建SpringBoot项目,仅选择Web模块即可 二.在POM文件中添加依赖 <!-- 添加servlet依赖模块 --> <depen ...
 - 温故知新,.Net Core遇见Consul(HashiCorp),实践分布式服务注册与发现
			
什么是Consul 参考 https://www.consul.io https://www.hashicorp.com 使用Consul做服务发现的若干姿势 ASP.NET Core 发布之后通过命 ...
 - springBoot-Quartz快速入门
			
springBoot-Quartz快速入门 开发环境 JDK1.8.Maven.Idea 技术栈 SpringBoot 2.1.6.quartz 2.3.0等 数据库准备 说明:数据库脚本由Quart ...
 - java设计模式(9):模板方法模式(TemplateMethod)
			
一,定义:模板方法模式定义了一个操作中的算法骨架,而将一些步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤. 二,类图: 三,通过小例子讲解: 这个模式一般用在 ...
 - PHP设计模式之策略模式(转)
			
介绍 策略模式:定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户. 封装:把行为用接口封装起来,我们可以把那些经常变化的部分,从当前的类中单独取出来,用接 ...
 - Linux学习之路第四天(运行级别)
			
linux 实用指令 指定运行级别 运行级别说明 0 :关机 1:单用户(找回丢失密码) 2.多用户状态没有网络服务 3.多用户状态有网络服务 4.系统未保留给用户 5.图形界面 6.系统重启 常用的 ...
 - ESP32-任务看门狗笔记
			
看门狗机制用于监控嵌入式系统运行并在发生不可知的软硬件故障时将系统复位.系统正常运行时,看门狗定时器溢出之前会被重置计数值,也就是"喂狗".定时器溢出意味着无法"喂狗&q ...