本文通过笔者经历的一个真实案例来介绍一个MySQL中的重要参数innodb_buffer_pool_size,希望能给大家带来些许收获,当遇到类似性能问题时可以多一种思考方式。

图片拍摄于大唐不夜城


问题背景

有个广西的客户,之前系统一直用的很流畅,最近反馈系统响应极慢,卡顿严重,希望我们尽快解决。

收到反馈以后我立马去查看服务器各项指标,微服务所在机器各项指标正常,但是数据库服务器已不堪重负,看一下top的输出:

数据库服务器的硬件配置为8核16G内存,最繁忙的时候系统负载已经达到了16,cpu利用率700%,可想而知系统当前服务质量有多糟糕。


自我思考

使用量突然上来了吗?

观察了使用人数的趋势图,是多了一些,但还在同一个数量级(toB的客户,一般都在一个可控的量)。

数据量突然上来了吗?

确实是多了一些,有几张表,之前一年多才30多万数据,最近一个月已经长到1百万级别,到底是业务上量了还是程序bug呢,还需要持续排查。

慢查多了吗?

是的,慢查很多,而且最近几天猛涨,怀疑是不是增加了新功能,根据慢SQL去查业务代码,确实增加了七八张报表,我尝试点了一下,确实很慢,高峰期前端几乎全是超时,太慢了。

toB系统业务复杂,OLTP和OLAP都兼备,MySQL应付OLTP很擅长,但是OLAP就有点捉襟见肘了,也许有人会说为什么不用大数据的那一套东西来解决OLAP的问题呢?

成本、成本、成本太高了,toB业务,大多数都部署在客户的自建机房中,最好能少引入或者不引入其他组件,最大限度降低各项成本,包括和客户的沟通成本,客户要付出的财力成本,后期的运维成本等等。


解决过程

铺垫了这么多,具体怎么解决呢?短期来看就是先采用垂直扩容的方式抵御一波,俗称升配置,长期来看的话需要梳理&优化慢查,采用读写分离等手段逐步优化。

话不多说,先联系客户升配置,8核16G变16核32G,希望第二天早高峰能给客户带来丝滑般的用户体验。

第二天我盯着数据库观察负载,确实好了一些,但终归还是凉凉了,只是来的比以往稍晚一些,一时间不知道怎么处理了,客户严重质疑我们的能力。

问题究竟出在哪里了呢?现在这个硬件配置已经很强悍了,感觉完全没有发挥出来,cpu最高才跑到800%。过往的工作中,有专门的DBA负责数据库的运维,遇到过一次升配的场景,升完以后有很明显的性能提升,那感觉刷刷的。

穷途末路的时候我拨通了老板的电话,和他沟通了目前的境遇,希望老同志能指点迷津,快速帮我捅破窗户纸,他有句话提醒了我,“为什么浙江客户的数据库没这个问题呢,配置一样,浙江客户的业务量还要更大一些,区别就是他们用的阿里云RDS,广西客户是自建MySQL,会不会有什么数据库的参数咱没有意识到”。

跟他聊完我立马去对比了阿里云RDS和自建MySQL的相关参数,有一个值非常可疑“innodb_buffer_pool_size“,浙江客户RDS中这个值为12G,而广西客户自建MySQL这个值才为128M,相差接近百倍,好奇心驱使着我快速一探究竟。

看下官方文档对于innodb_buffer_pool的解释:

  • The buffer pool is a memory area that holds cached data for tables, indexes, and other auxiliary buffers. For efficiency of high-volume read operations, the buffer pool is divided into pages that can potentially hold multiple rows. For efficiency of cache management, the buffer pool is implemented as a linked list of pages; data that is rarely used is aged out of the cache, using a variation of the LRU algorithm. For more information, see Section 15.5.1, “Buffer Pool”. InnoDBInnoDB

    The size of the buffer pool is important for system performance:

    • InnoDB allocates memory for the entire buffer pool at server startup, using operations. The innodb_buffer_pool_size system variable defines the buffer pool size. Typically, a recommended innodb_buffer_pool_size value is 50 to 75 percent of system memoryinnodb_buffer_pool_size can be configured dynamically, while the server is running. For more information, see Section 15.8.3.1, “Configuring InnoDB Buffer Pool Size”. malloc()

    • On systems with a large amount of memory, you can improve concurrency by dividing the buffer pool into multiple buffer pool instances. The innodb_buffer_pool_instances system variable defines the number of buffer pool instances.

    • A buffer pool that is too small may cause excessive churning as pages are flushed from the buffer pool only to be required again a short time later.

    • A buffer pool that is too large may cause swapping due to competition for memory.

提取出这么几个重要信息:

1.缓冲池是保存表、索引和其他辅助缓冲区的缓存数据的内存区域;

2.缓冲池的大小对MySQL的性能很重要;

3.推荐的大小是物理内存的50%到75%;

4.inndb_buffer_pool_size可以在MySQL运行时动态调整;

5."Configuring InnoDB Buffer Pool Size"这个配置手册中提到默认值为128兆。

再看看《MySQL技术内幕InnoDB存储引擎》这本书中关于缓冲池的介绍:

缓冲池简单来说就是一块内存区域,通过内存的速度来弥补磁盘速度较慢对数据库性能的影响。在数据库中进行读取页的操作,首先将从磁盘读到的页放在缓冲池中,这个过程称为将页“FIX“到缓冲池中。下一次再读相同的页时,首先判断该页是否在缓冲池中,若在缓冲池中,称该页在缓冲池中被命中,直接读取该页,否则,读取磁盘上的页。

做了一定的了解之后我决定动手去改一下这个值看看效果,之前提到客户已经把数据库服务器的配置扩到了16核32G,那我就把inndb_buffer_pool_size设置为32G*0.75=24G。

--注意:

--1.这里的单位是字节

--2.这是动态调整,长远来看这个配置应该放到配置文件中,防止重启丢失

set global innodb_buffer_pool_size = 25769803776

调完以后效果显著,我拿了几个耗时严重的SQL做了对比,查询时间减少一半以上,慢查数量明显下降,看看此时的数据库负载情况

调整缓冲池大小之前cpu和负载都很高,但是内存占用很低,调整完以后cpu和负载明显下降,内存占用高了,这正是我们所期待的效果。

看看客户给我们的反馈


总结

问题暂时告一段落,虽说没有100%的解决问题,但也解决了70%-80%的问题,那些剩余的20%-30%需要开发人员去优化代码,硬件扩容并不是银弹,庆幸的是,经过这次调整应该能给开发人员争取一些时间来优化代码。

另一方面也折射出自己对数据库的认识只是停留在开发视角的一些知识,比如SQL优化、索引的匹配、慢查优化等等,对于底层原理性的东西欠缺太多,有人会说这类东西应该交给DBA负责,这么说倒也没什么问题,但现实情况是有些团队就是没有配备DBA的,只能开发顶,再者说,作为开发而言,对于这类知识不一定要熟练掌握,但起码应该有一些初步的认识。


推荐阅读

MySQL如何使用内存 (oracle.com)

https://docs.oracle.com/cd/E17952_01/mysql-8.0-en/memory-use.html

调整innodb_buffer_pool_size

Configuring InnoDB Buffer Pool Size (oracle.com)

终于做了一把MySQL调参boy的更多相关文章

  1. Python中Gradient Boosting Machine(GBM)调参方法详解

    原文地址:Complete Guide to Parameter Tuning in Gradient Boosting (GBM) in Python by Aarshay Jain 原文翻译与校对 ...

  2. hyperopt自动调参

    hyperopt自动调参 在传统机器学习和深度学习领域经常需要调参,调参有些是通过通过对数据和算法的理解进行的,这当然是上上策,但还有相当一部分属于"黑盒" hyperopt可以帮 ...

  3. GBDT调参总结

    一.GBDT类库弱学习器参数 二.回归 数据集:已知用户的30个特征,预测用户的信用值 from sklearn.ensemble import GradientBoostingRegressor f ...

  4. [调参]CV炼丹技巧/经验

    转自:https://www.zhihu.com/question/25097993 我和@杨军类似, 也是半路出家. 现在的工作内容主要就是使用CNN做CV任务. 干调参这种活也有两年时间了. 我的 ...

  5. scikit-learn 梯度提升树(GBDT)调参小结

    在梯度提升树(GBDT)原理小结中,我们对GBDT的原理做了总结,本文我们就从scikit-learn里GBDT的类库使用方法作一个总结,主要会关注调参中的一些要点. 1. scikit-learn ...

  6. gbdt调参的小结

    关键部分转自http://www.cnblogs.com/pinard/p/6143927.html 第一次知道网格搜索这个方法,不知道在工业中是不是用这种方式 1.首先从步长和迭代次数入手,选择一个 ...

  7. scikit-learn 梯度提升树(GBDT)调参笔记

    在梯度提升树(GBDT)原理小结中,我们对GBDT的原理做了总结,本文我们就从scikit-learn里GBDT的类库使用方法作一个总结,主要会关注调参中的一些要点. 1. scikit-learn ...

  8. scikit-learn随机森林调参小结

    在Bagging与随机森林算法原理小结中,我们对随机森林(Random Forest, 以下简称RF)的原理做了总结.本文就从实践的角度对RF做一个总结.重点讲述scikit-learn中RF的调参注 ...

  9. word2vec参数调整 及lda调参

     一.word2vec调参   ./word2vec -train resultbig.txt -output vectors.bin -cbow 0 -size 200 -window 5 -neg ...

随机推荐

  1. 在idea的java开发中字符串length()方法获取长度与赋值不符的问题

    最近在开发中用到length()方法获取中文字符串的长度,发现获得的长度与实际不符.比如个String类型赋值为"中",但获取长度却是2. 这让我百思不得其解,后来突然想起来我在研 ...

  2. day03 MySQL数据库之主键与外键

    day03 MySQL数据库之主键与外键 昨日内容回顾 针对库的基本SQL语句 # 增 create database meng; # 查 show databases; shwo create da ...

  3. Spark(七)【RDD的持久化Cache和CheckPoint】

    RDD的持久化 1. RDD Cache缓存 ​ RDD通过Cache或者Persist方法将前面的计算结果缓存,默认情况下会把数据以缓存在JVM的堆内存中.但是并不是这两个方法被调用时立即缓存,而是 ...

  4. MySQL(2):数据管理

    一. 外键概念: 如果公共关键字在一个关系中是主关键字,那么这个公共关键字被称为另一个关系的外键.由此可见,外键表示了两个关系之间的相关联系.以另一个关系的外键作主关键字的表被称为主表,具有此外键的表 ...

  5. Java Timestamp 类的使用

    很简单,我们可以这样声明 Timestamp ts=new Timestamp(new Date().getTime());这样我们就可以得到时间比较具体的一个类型转换!!! 在开发web应用中,针对 ...

  6. JS - 获取当前的时间,并且转换成年 - 月 - 日格式!

    先获取当前时间,并转换成年月日格式! function getNowFormatDate() { var date = new Date(); var seperator1 = "-&quo ...

  7. Next_day()函数的用法

    一.定义 NEXT_DAY(date,char)  date参数为日期型,  char:为1~7或Monday/Mon~Sunday/    指定时间的下一个星期几(由char指定)所在的日期,  c ...

  8. 机器学习算法中的评价指标(准确率、召回率、F值、ROC、AUC等)

    参考链接:https://www.cnblogs.com/Zhi-Z/p/8728168.html 具体更详细的可以查阅周志华的西瓜书第二章,写的非常详细~ 一.机器学习性能评估指标 1.准确率(Ac ...

  9. show_slave_status参数详解

    #这个是指slave 连接到master的状态 #当前在等待主发送事件 Slave_IO_State: Waiting for master to send event #master地址 Maste ...

  10. Firebug: Net Panel 使用详解

    Introduction to Firebug: Net Panel Since there is not much user documentation related to Firebug fea ...