微信公众号:我其实目前没有耶
我是一个互联网公司的螺丝钉;
魔术师耿

mysql服务器性能瓶颈分析和内存优化

前言

开发阶段,对项目中mysql使用在代码层面已经做了最大努力的优化;

  • 大表减少关联查询,进行单表查
  1. 关联字段添加索引(一个表最多16个索引,最大索引长度256字节)
  2. 对关联查询建立联合索引,尽量走覆盖索引
  • 使用缓存,(java本地缓存;redis缓存)
  1. 本地堆内缓存 HashMap,ConcurrentHashMap,Guava的ConcurrentLinkedHashMap;

    要注意设置过期时间,防止对象长时间放在堆里老年代;累计引起FULL GC

  2. ehcache 可以使用队外内存

  3. redis 访问存在网络开销,没有本地内存快

  • 慢查询优化
  1. 开启慢查询开关,慢查询日志保存目录文件

  2. 使用mysqldumpslow或者pt-query-digest 定位慢查询sql,(我用pt-query-digest)

  3. 拿到sql语句 explan 查看执行计划,分析为什么慢,是否还有优化空间

    a.是否有filesort,临时表,排序;

    ​ 多表关联查询group by : sql执行效率和数据量、where过滤条件都有关系;最终数据量越大,group by越慢

    b.是否有回表查询(聚簇索引和非聚簇索引在B+树的数据存储上的区别)

    c.优化大表分页查询

    d.是否建立的索引没走

  • 大表按照月份分表,按照有业务含义的字段取模分表

  • 单线程处理改成多线程并发处理任务

  1. 一个任务处理要放在一个事务里;保证ACID的特性(Atomicity,Consistency,Isolation,Durability)
  2. 任务的处理逻辑被打包成一个Runnable 投入到线程池里去执行业务逻辑(在一个实现了Runnable接口的类里面,注入自己的任务处理Service )
  3. 上面有一个线程分页去mysql里取出待处理的任务参数,打包成个对象丢到JVM本地的队列里(每次丢数据的时候检查队列的长度,是不是有任务积压没被处理掉,需要等的时候就sleep(一会儿),)
  4. JVM内并发处理任务,synchronized对尽可能最小的任务隔离级别添加锁,比如userId
  • 单JVM改成多个服务

    1. 一个线程去查mysql,把任务对象参数放到一个redis队列;(同样检查消息积压)

    2. 每个JVM内起一个EventBootStrap 的线程 用来专门监听这个redis队列List1,取一部分数据到本地JVM 的队列ArrayBlockingQueue(给后面的线程池用) ,定义一个List(投入线程池添加,任务正常结束移除;用来处理异常情况需要的二次加载处理,比如JVM宕机,手动中断后再次启动继续处理)

      https://blog.csdn.net/z69183787/article/details/46986963

      注册一个JVM关闭的钩子方法

      Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {  @Override  public void run()  {  //把从redis拉取过来的,本地还没处理完的数据,刷到redis一个暂时存储的其他List2,//下次从redis的List1中拉取数据前,先把List2中的数据转移到JVM本地System.out.println("Execute Hook.....");  }  }));
      
    3. 线程池执行任务的时候,使用Redis的分布式锁来保证两个JVM中的后一个事件不能比前一个事件先执行,

前段时间闲来无事;别人给了我个连接,我刚好可以上去看看公司的服务器配置;顺带看看有什么问题没;

硬件配置

公司mysql配置
32核64G(独享型sn1)
内网IP: 172.xx.xx.xx
外网IP: 118.xx.xx.xx(按量付费30Mbps)
磁盘: 3块SSD (一块2T的磁盘包年包月2000 共两块2T的,和一个100G的)
IO性能 : 最大IOPS 20000次/秒
最大吞吐量 256MBps
成本评估:8244元/月

运行情况

磁盘IO监控详情

最近一次
a.抽取统计信息: 两个动作,每个动作开启50个线程共100个线程,select 联合查询后 单表批量insert
磁盘IO可以跑到最高 150MBps
b.抽取事件: 对不同的事件类型,顺序抽取,开启50进行抽取, 分页关联查询后, 单表单条插入
磁盘IO可以跑到最高 100MBps

c.确认事件: 200个线程 并行确认对userId加锁 ,cpu运算后,对107个表进行插入修改,(其中一个表有100个分表)
磁盘IO可以跑到最高 80-100MBps 晚上 ; 白天只有30-50MBps

CPU监控

CPU Idle cpu空闲 80%
告警设置:CPU Other大于20%且持续10分钟时产生告警通知 0.58%
告警设置:CPU System大于20%且持续10分钟时产生告警通知 2.12%
告警设置:CPU User大于60%且持续10分钟时产生告警通知 15%
告警设置:CPU IOWait大于20%且持续10分钟时产生告警通知 6%
告警设置:CPU使用率大于80%且持续10分钟时产生告警通知

内网监控

入站速率在55Mbps-70Mbps
出站速率在 500Mbps-750Mbps 平均600Mbps
告警设置:内网入站速率大于51200Kbps且持续10分钟时产生告警通知
告警设置:内网出站速率大于51200Kbps且持续10分钟时产生告警通知

内存监控

内存使用率91%,已经产生告警;这么高的硬件配置了;感觉里面一定有问题

发现问题:


top 命令后 按1 可以查看每个核的cpu使用率
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7QawdlP1-1591166869516)(./resource/mysql_top.png )]

翻阅资料

「mysql5.7内存占用持续过高」

SHOW GLOBAL STATUS LIKE 'Open%tables' ;
--
-- Open_tables       2000    : 打开后在缓存中的表数量
-- Opened_tables    41486219 : 打开的所有表数量
SHOW GLOBAL VARIABLES LIKE 'table_open_cache' ; -- 查看 table_open_cache
-- table_open_cache 2000
set global table_open_cache = 2048; -- (立即生效重启后失效)
/*
MySQL 配置文件 my.cnf 中 mysqld 下添加 table_open_cache
[mysqld]
table_open_cache = 2048
*/

table_open_cache指定表高速缓存的大小。
每当MySQL访问一个表时,如果在表缓冲区中还有空间,该表就被打开并放入其中,这样可以更快地访问表内容。
通过检查峰值时间的状态值Open_tables和Opened_tables,可以决定是否需要增加table_open_cache的值。
如果你发现open_tables等于table_open_cache,
并且opened_tables在不断增长,那么你就需要增加table_open_cache的值了(上述状态值可通过SHOW GLOBAL STATUS LIKE ‘Open%tables’获得)。
注意,不能盲目地把table_open_cache设置成很大的值,设置太大超过了shell的文件描述符(通过ulimit -n查看),造成文件描述符不足,从而造成性能不稳定或者连接失败

ulimit -n
65535
## mysql最大连接数
show variables like '%max_connections%';
-- max_connections  10000

「MySQL 优化之 table_open_cache」
table_open_cache
表文件描述符的缓存大小
( 当打开一个表后 会把这个表的文件描述符缓存下来 )

# table_open_cache
默认值 2000
最小值 1
最大值 524288

table_open_cache 设置多少合适

不是越大越好 table_open_cache过大占用大量文件描述符资源而不释放
用尽了系统文件描述符资源导致无法接入新的连接

如何判断 table_open_cache 大小是否够用?
可根据MySQL的两个状态值来分析
通过以上两个值来判断 table_open_cache 是否到达瓶颈
当缓存中的值open_tables 临近到了 table_open_cache 值的时候
说明表缓存池快要满了 但 Opened_tables 还在一直有新的增长 这说明你还有很多未被缓存的表
这时可以适当增加 table_open_cache 的大小
「MySQL 5.7 参考手册 - table_open_cache」
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yH3BRlMw-1591166869517)(./resource/dev_mysql_02.png )]

table_open_cache默认2000 最大 524288
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-szQOaNjB-1591166869518)(./resource/dev_mysql_01.png )]

  • Opened_tables

The number of tables that have been opened. If Opened_tables is big, your table_open_cache value is probably too small.

  • Table_open_cache_hits (命中数)

The number of hits for open tables cache lookups.

  • Table_open_cache_misses(未命中数)

The number of misses for open tables cache lookups.

  • Table_open_cache_overflows(溢出数)

The number of overflows for the open tables cache. This is the number of times, after a table is opened or closed, a cache instance has an unused entry and the size of the instance is larger than table_open_cache / table_open_cache_instances.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2eGWsIIy-1591166869518)(./resource/dev_mysql_03.png )]
open_files_limit mysql 可以从操作系统拿到的文件描述符的个数

open_files_limit 的实际值是取的下面4个值的最大值

  • 10 + max_connections + (table_open_cache * 2)

10+最大连接数+(表4打开缓存*2)

  • max_connections * 5

最大连接数*5

  • Operating system limit if that limit is positive but not Infinity

操作系统限制如果该限制为正但不是无穷大

  • If operating system limit is Infinity: open_files_limit value if specified at startup, 5000 if not

如果操作系统限制是无限的:如果在启动时指定了“打开文件”限制值,则为5000
服务器尝试使用这些值的最大值来获取文件描述符的数量。如果无法获取这么多描述符,服务器将尝试获取系统允许的尽可能多的描述符。
在MySQL无法更改打开文件数的系统上,有效值为0。
在Unix上,该值不能设置为大于ulimit-n。(我这台机器上是 65535)
max_connections(我们运维和dba老师设置的是10000)

open_files_limit

= max(10 + max_connections + (table_open_cache * 2) ,max_connections * 5, ulimit -n )

尝试解决

我自己的环境分析设置

我自己环境上62G内存被占用到只剩5.5G 达到91%
Opened_tables=41486219 远远大过 Open_tables=table_open_cache=2000
表明缓存池已经远远不够了,

SELECT COUNT(*) TABLES FROM information_schema.TABLES ;
-- 2573
SELECT COUNT(*) TABLES FROM information_schema.TABLES
WHERE table_schema  like 'ir%' or table_schema = 'incomerecognition';
-- 1636
SELECT COUNT(*) TABLES  FROM information_schema.TABLES
WHERE table_schema  like 'Order%';
-- 260SHOW GLOBAL STATUS;SHOW GLOBAL STATUS LIKE 'table_open_cache%' ;
-- Table_open_cache_hits        5957402859
-- Table_open_cache_misses        41645844
-- Table_open_cache_overflows     41624078        

open_files_limit

= max(10 + max_connections + (table_open_cache * 2) ,max_connections * 5, ulimit -n )

=max(10 + 10000 + (table_open_cache * 2) ,50000 , 65535 )

我这里先谨慎点 table_open_cache 设置成 5000吧,(我觉得 最大不应该超过20000 )
毕竟 操作系统文件描述符为65535 , 还是给操作系统其他资源预留 资源的; 除非调大 操作系统最大文件描述符的最大限制
但是 这是个mysql服务器; 并不是给Netty使用的 IM服务器

然后去试下,效果

SHOW GLOBAL STATUS LIKE 'Open%tables' ;
--
-- Open_tables       2000    : 打开后在缓存中的表数量
-- Opened_tables    41486219 : 打开的所有表数量
SHOW GLOBAL VARIABLES LIKE 'table_open_cache' ; -- 查看 table_open_cache
-- table_open_cache 2000
set global table_open_cache = 5000; -- (立即生效重启后失效)
/*
MySQL 配置文件 my.cnf 中 mysqld 下添加 table_open_cache
[mysqld]
table_open_cache = 5000
*/

验证结果

测试后发现并没有什么卵用

请教DBA老师
DBA让我调整这三个参数

performance_schema_max_table_instances=400
table_definition_cache=400
table_open_cache=256

这三个参数改下,需要重启
这3个参数要不要写在配置my.cnf中呀,要不然重启后不是就变了
需要加配置文件

mysql内存是占用后不会释放,
还有buffer_pool也根据主机内存设置

table_open_cache为什么需要改小呢?
少缓存表可以少占用内存
太多了也没意义

  • performance_schema_max_table_instances

The maximum number of instrumented table objects
插装表对象的最大数目

  • table_definition_cache

The number of table definitions (from .frm files) that can be stored in the definition cache
可以存储在定义缓存中的表定义的数量(来自.frm文件)

过了两天观测数据,好像生效了

发文前观看,已经恢复正常,使用率在61%,没再告警,

mysql性能瓶颈分析和内存占用高的优化相关推荐

  1. nginx内存占用高---内存池使用思考

    nginx内存占用高-内存池使用思考 问题现象 nginx top 进程 虚拟内存 200G 实际内存5G 和 CDN 平台相比要高很多 排查思路 使用pmap -p 进程号,发现从系统角度确实 有分 ...

  2. java事务占用内存吗,如何排查java应用中CPU使用率高或内存占用高的问题

    如何排查java应用中CPU使用率高或内存占用高的问题?这类问题的排查步骤基本通用的.现在通过一个具体的例子来说明. 问题描述 最近有个线上项目每天0点过后CPU使用率会上升至200%到300%. 排 ...

  3. Java 分析 程序CPU 占用高的原因

    Java 分析 程序CPU 占用高的原因 背景:最近突然发现线上测程序长时间CPU 占用过高.内存确没有什么消耗.这种情况下可以排除死锁(一般死锁之后,如果不是自旋锁的话,CPU 占用都不会很高),也 ...

  4. mc服务器java占用过大_如何排查java应用中CPU使用率高或内存占用高的问题

    点击上方"Java知音",选择"置顶公众号" 技术文章第一时间送达! 作者:MnameHZJ my.oschina.net/u/1420452/blog/224 ...

  5. win7计算机内存占用高,WIN7系统电脑内存占用高的解决办法有哪些

    现在经常很多用户的WIN7系统内存都占用太多,导致电脑的运行速度变得很慢.所以这里小编就给大家介绍一下如何解决这个内存占用高的办法. Win7内存占用高解决方法一 1:单击 按钮,在搜索框输入&quo ...

  6. Win11内存占用高怎么办,Win11内存占用高解决方法

    ​Win11内存占用高怎么办?Win11系统是目前非常火热的电脑操作系统,很多用户安装使用Win11系统后发现系统内存占用率非常高,不知道win11内存占用高怎么解决,我们可以尝试通过关闭一些不需要的 ...

  7. 计算机内存占用过高,电脑内存占用高怎么办 Win7内存占用高解决办法

    Win7系统在正常使用的时候会占用很多资源,比如网络诊断,缓存还有其他各种平时大部分时候我们都用不上的资源,如果我们电脑本身内存比较小只有2G内存或者以下,打开程序稍微多加个就会造成Win7内存占用高 ...

  8. win7计算机内存占用高,win7系统内存占用高的解决方法

    我们在操作win7系统电脑的时候,常常会遇到win7系统内存占用高的困惑吧,一些朋友看过网上零散的win7系统内存占用高的处理方法,并没有完完全全明白win7系统内存占用高是如何解决的,今天小编准备了 ...

  9. 如何清理占用计算机内存,win10如何清理电脑内存占用高怎么办

    随着Win10的更新,越来越多的用户将系统升级到了Win10,可是不少Win7.Win8系统的用户升级后,发现C盘内存空间严重变少了,磁盘占用比之前的系统还多,win10如何清理电脑内存占用高怎么办? ...

最新文章

  1. LSM树——放弃读能力换取写能力,将多次修改放在内存中形成有序树再统一写入磁盘...
  2. 利用MATLAB实现移动目标的TDOA/FDOA定位算法
  3. XCode 4.2(4.1)真机调试及生成IPA全攻略
  4. 判断JavaScript对象为null或者属性为空
  5. Codeforces 835 F Roads in the Kingdom(树形dp)
  6. ps图像压缩插件:TinyPNG and TinyJPG for Mac 支持ps2021
  7. 收藏!架构师需要掌握的99条铁律
  8. 平安夜、圣诞节设计素材和灵感|撒糖(PNG免扣素材)
  9. DIY一套10倍\20倍\30倍光学变焦高清航拍方案(变焦云台相机方案)
  10. 世事无常,深信服及其他
  11. Virtualbox以及VWare在Win10下的不兼容
  12. 部署FIM 2010 R2——7验证不同林之间相同用户名密码同步
  13. 如果计算机正执行屏幕保护程序 当用户,计算机一级考试参考试题(含答案)讲节一.doc...
  14. 百度地图离线API及地图数据下载工具-尝鲜篇
  15. 编写函数:字符串的小写转大写(Append Code)
  16. 数据链路层详细解剖,并完成实现不同交换机相同VLAN主机之间的通信实验
  17. 1.2 逻辑电路基础
  18. 从玩具到工具,OPPO新一代智能眼镜Air Glass正式发布
  19. vue-cli 原理分析
  20. 学生表 成绩表 课程表 教师表

热门文章

  1. 关于api-ms-win-crt-runtime-l1-1-0.dll 丢失
  2. 百度地图BaiduMapsApiASDemo中驾车路线RoutePlanDemo的个人理解
  3. java计算机毕业设计幼儿早教系统软件设计与实现(附源码、数据库)
  4. 机器学习 基于IRIS鸢尾花数据集进行聚类分析
  5. Matlab函数语法(函数可以接受多个输入参数,并可能返回多个输出参数)
  6. 华华给月月准备礼物(二分)
  7. ArcGis For JavaScript API (测量工具)
  8. 京东金融加班新规,员工愤怒了:这是逼着我们辞职吗?
  9. 谁来帮帮我 help
  10. 股粮网:最新中国城市GDP百强榜:你的家乡排第几?