MySQL的内存和相关问题排查

存储 存储软件 MySQL
我们都知道数据库是IO密集型一类应用,为了提高其性能大量使用内存代替文件(交换分区)的IO操作是保证数据库稳定、高效的基本原则。那么数据库是如何使用内存的,我们如何查看数据库内存的占用,如何通过通过数据库内存配置设置提高其性能?

 我们都知道数据库是IO密集型一类应用,为了提高其性能大量使用内存代替文件(交换分区)的IO操作是保证数据库稳定、高效的基本原则。那么数据库是如何使用内存的,我们如何查看数据库内存的占用,如何通过通过数据库内存配置设置提高其性能?本文虫虫就以Mysql数据库(InnoDB引擎)为例和大家一起了解下Linux数据库和内存相关的主题。

读取内存数据非常快,为了提高性能我们要尽***可能把数据集都放到内存中以保证高效。但是Swap交换分区作为一个救命的稻草,我们还必须要给mysql设置,防止突发情况下内存不够,mysql服务直接被OOM杀掉的情况。同时mysql交换分区占用也是我们衡量一个数据是否健康与否的手段,如果一个数据库频繁的使用了swap则说明,我们需要人工干预优化数据库了。

内存占用

在Linux下,我们可以通过使用一些shell命令来了解MySQL的内存使用情况。

首先使用ps命令来查看mysqld进程的内存使用情况:

  1. ps -eo size,pid,user,command --sort -size|grep mysqld 
  2. |awk '{hr=$1/1024;printf("%13.2f MB",hr)} {for (x=4;x<=NF;x++){printf("%s",$x)}print ""}' 
  3. |cut -d "" -f2|cut -d "-" -f1 

MySQL的内存和相关问题排查

  1. 1990.88 MB/usr/local/mariadb/bin/mysqld 
  2. 0.49 MB/bin/sh/usr/local/mariadb/bin/mysqld_safe 

top命令也可以查看对应上面的结果也可以用top来得到:

  1. top -b -o %MEM -n1 -p $(pidof mysqld) | grep PID -A 

MySQL的内存和相关问题排查

  1. PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 
  2. 2239 mysql 20 0 2108536 316836 7548 S 0.0 4.0 48:47.37 mysqld 

其中,VIRT(virtual memory usage)表示mysql使用的虚拟内存总量。它包括所有代码,数据和共享库以及最终要被置换出的页面。

RES(resident memory usage) 常驻内存,包括当前进程使用的内存,不包括置换出的内存。

SHR(shared memory) 共享内存,进程使用的的共享内存,也包括其他进程的共享内存。

交换分区

我们再来检查检查mysqld是否正在使用交换分区,首先用free -m检查是否有用到交换分区。

  1. free -m 

MySQL的内存和相关问题排查

  1. total used free shared buff/cache available 
  2. Mem: 7822 5091 178 83 2552 2290 
  3. Swap: 3999 2 3997 

上面结果了,系统使用少量的交换分区(2M),那怎么判断是不是MySQL用的呢?我们来验证:

  1. cat /proc/$(pidof gitlab)/status | grep Swap 

MySQL的内存和相关问题排查

 

VmSwap:0 kB

可见mysqld不没用用到交换区,说明我的mysqld在高效运行中。

这儿我们提供一个脚本,遍历每一个进程,找出那些进程使用了交换分区:

  1. for i in $(ls -d /proc/[0-9]*) 
  2. do 
  3. out=$(grep Swap $i/status 2>/dev/null
  4. if [ "x$(echo $out | awk '{print $2}')" != "x0" ] && [ "x$(echo $out | awk '{print $2}')" != "x" ] 
  5. then 
  6. echo "$(ps -p $(echo $i | cut -d'/' -f3) 
  7. | tail -n 1 | awk '{print $4'}): $(echo $out | awk '{print $2 $3}')" 
  8. fi 
  9. done 

MySQL的内存和相关问题排查

 

当然,交换中的页面可能已经存在很长时间了,自从使用一次后,后面就没有在用过。为了获取实时交换分区情况,我们可以用vmstat

  1. vmstat 1 10 

MySQL的内存和相关问题排查

 

在这个服务器上,我们可以看到mysqld没有使用交换,如果系统内存充足,但是mysqld还占用了部分交换分区,是怎么回事?怎么排查呢?

如果遇到这种情况,可能的直接原因有swappiness和Numa。

Swappiness

swappiness参数控制内核将进程移出物理内存并将其放入交换磁盘分区的趋势。我们之前也说过了磁盘IO操作要比RAM慢很多很多,因此如果进程过于频繁地从内存中置换出,这会导致系统和应用程序的响应时间变慢。高swappiness值意味着内核更容易取消内存页面。低swappiness相反,内核将不太容易取消内存页面。swappiness值越高,系统内存置换的越多。

linux下系统(CentOS、Red Hat、ubuntu)默认的swappiness值为60。如果内存较小则应适当调高这个值。对于内存足够的MySQL服务器,这个默认设置就有点太高了,应该减少。一般情况下,业界建议这个值可以设置到5.或者更小。设置swappiness方法是使用sysctl命令直接改变内核参数。

  1. sysctl -w vn.swappinness = 1 

NUMA设置

还有一个方面就是NUMA设置。对于具有多个NUMA核心的服务器,建议将NUMA模式设置为交错,以平衡所有节点的内存分配。 在***的MySQL 8.0中支持为InnoDB设置NUMA。可以在配置通过启动:innodb_numa_interleave = 1

要检查是否有多个NUMA节点,可以使用numactl -H

这是两种不同的输出:

MySQL的内存和相关问题排查

 

MySQL的内存和相关问题排查

 

我们可以看到,当有多个NUMA节点(下)时,默认情况下,内存不会在所有节点之间平均分配。这可以导致更多内存置换。

文件系统缓存

默认情况下,Linux将使用文件系统会对所有的I/O操作进行缓存(这是不建议使用MyISAM的原因之一,MyISAM存储引擎依赖于FS缓存,并且可能导致丢失数据)。Mysql InnoDB引擎中使用O_DIRECT作为innodb_flush_method,MySQL将绕过文件系统缓存,不会将任何FS Cache Memory用于数据文件(* .ibd)。

当然在MySQL中使用的其他非数据文件仍会使用FS Cache。我们来看个例子:

  1. dbsake fincore binlog.000017 
  2. binlog.000017: total_pages=120841 cached=50556 percent=41.84 
  3. ls -lh binlog.000017 
  4. -rw-r----- 1 mysql mysql 473M Sep 18 07:17 binlog.000017 
  5. free -m 
  6. total used free shared buffers cached 
  7. Mem: 5965 4608 1356 128 435 2456 
  8. -/+ buffers/cache: 1716 4249 
  9. Swap: 2045 30 2015 
  10. dbsake uncache binlog.000017 
  11. Uncached binlog.000017 
  12. free -m 
  13. total used free shared buffers cached 
  14. Mem: 5965 4413 1552 128 435 2259 
  15. -/+ buffers/cache: 1718 4247 
  16. Swap: 2045 30 2015 

开始检查文件系统缓存中存在多少二进制日志(使用dbsake fincore),我们可以看到473M中有42%使用RAM作为FS缓存。然后我强制取消在缓存中使用这些页面(使用fincore uncache),结果,我们释放了+/- 195MB的RAM。

责任编辑:武晓燕 来源: 今日头条
相关推荐

2021-06-28 08:00:00

Python开发编程语言

2021-02-26 13:35:46

JavaCPU内存

2024-08-19 00:10:00

C++内存

2022-07-03 20:31:59

JVMJava虚拟机

2015-07-20 10:23:24

NET内存问题排查

2022-01-26 19:42:05

MySQL乱码排查

2021-11-14 05:00:56

排查Sdk方式

2024-01-05 09:23:09

Linux系统内存内存指标

2022-02-08 17:17:27

内存泄漏排查

2018-08-10 15:00:42

服务器内存排查

2019-12-17 10:01:40

开发技能代码

2010-05-11 13:42:36

MySQL隐藏空间

2011-03-31 14:05:01

mysql

2019-04-29 14:23:46

Java服务器CPU

2014-02-27 13:30:26

CacheLinux系统内存不足

2022-04-11 15:10:34

微服务迁移goroutine

2021-07-30 20:59:21

MySQL内存.参数

2015-09-21 09:10:36

排查修复Windows 10

2019-01-29 08:41:16

MySQL性能突发事件

2022-05-08 09:11:44

WiFi树莓派GO
点赞
收藏

51CTO技术栈公众号