Linux有很多很好的内存、IO调度机制,但是并不会适用于所有场景。对于运维人员来说,Linux比较让人头疼的一个地方是:它不会因为MySQL很重要就避免将分配给MySQL的地址空间映射到swap上。对于频繁进行读写操作的系统而言,数据看似在内存而实际上在磁盘是非常糟糕的,响应时间的增长很可能直接拖垮整个系统。所以,作为运维人员,怎样做到尽量避免MySQL惨遭Swap的毒手将显得尤为重要!

SWAP是操作系统虚拟出来的一部分内存地址,它的物理存储元件是磁盘。在备份数据或恢复数据时,文件系统会向Linux系统请求大量的内存作为cache。在物理内存使用殆尽时候,为了确保程序运行,往往会将另外的一些占用物理内存地址空间的程序映射到swap分区上。

操作系统设置swap的目的
程序运行的一个必要条件就是足够的内存,而内存往往是系统里面比较紧张的一种资源。为了满足更多程序的要求,操作系统虚拟了一部分内存地址,并将之映射到swap上。对于程序来说,它只知道操作系统给自己分配了内存地址,但并不清楚这些内存地址到底映射到物理内存还是swap。
物理内存和swap在功能上是一样的,只是因为物理存储元件的不同(内存和磁盘),性能上有很大的差别。操作系统会根据程序使用内存的特点进行换入和换出,尽可能地把物理内存留给最需要它的程序。但是这种调度是按照预先设定的某种规则的,并不能完全符合程序的需要。一些特殊的程序(比如MySQL)希望自己的数据永远寄存在物理内存里,以便提供更高的性能。于是操作系统就设置了几个api,以便为调用者提供"特殊服务"。

服务器产生Swa分区的原因
1)copy一个大文件,比如上百G的backup包
2)正在mysqldump以及mysql import一个很大的库的时候。
3)大批量的并发操作的io writer和io read操作。

MySQL程序运行时,物理内存为MySQL分配了大量的物理地址空间,以提高执行的速率。为了避免在执行消耗大量内存的操作时将MySQL所拥有的部分物理内存地址空间映射到swap分区上(比如出现了MySQL服务器Swap满了100%导致db很慢很卡的现象),可做一下调整(解决办法):
1)改系统内核参数/proc/sys/vm/swappiness。调整系统使用swap分区的倾向性,数值越低越倾向于释放文件系统的cache,不能避免Linux系统使用swap分区。swappiness=0表示最大限度使用物理内存,然后才是swap分区。swappiness=100表示积极使用swap分区,并且将内存上的数据及时的映射到swap分区上。

/proc/sys/vm/swappiness的内容改成0(临时),/etc/sysctl.conf上添加vm.swappiness=0(永久)这个参数,Linux是倾向于使用swap,还是倾向于释放文件系统cache。在内存紧张的情况下,数值越低越倾向于释放文件系统cache。当然,这个参数只能减少使用swap的概率,并不能避免Linux使用swap。

2)改MySQL参数innodb_flush_method,开启O_DIRECT模式。Innodb的buffer pool会直接绕过文件系统cache来访问磁盘,但是redo log依旧会使用文件系统cache。Redo Log是覆写模式的,即使使用了文件系统的cache也不会占用太多

3)加MySQL配置参数memlock。将MySQL锁定在内存中防止被swapping out。这个参数会强迫mysqld进程的地址空间一直被锁定在物理内存上,对于os来说是非常霸道的一个要求。必须要用root帐号来启动MySQL才能生效。

4)指定MySQL使用大页内存(Large Page)。Linux上的大页内存是不会被换出物理内存的,和memlock有异曲同工之妙。

5)临时释放锁占据的swap。

=========================================================

在Mysql数据库维护中,会遇到的一个现象: MySQL内存持续增加,最高时物理内存消耗达到90%以上,导致swap使用率100%,进而造成内存不足,系统自动kill mysql进程。Mysql服务挂掉,查看Mysql的error日志信息:
[ERROR] InnoDB: Unable to lock /usr/local/mysql/var/ibdata1, error: 11
或者
InnoDB: mmap(137363456 bytes) failed; errno 12
2016-03-01 01:38:42 13064 [ERROR] InnoDB: Cannot allocate memory for the buffer pool
2016-03-01 01:38:42 13064 [ERROR] Plugin 'InnoDB' init function returned error.
2016-03-01 01:38:42 13064 [ERROR] Plugin 'InnoDB' registration as a STORAGE ENGINE failed.
2016-03-01 01:38:42 13064 [ERROR] Unknown/unsupported storage engine: InnoDB
2016-03-01 01:38:42 13064 [ERROR] Aborting

出现上面报错的原因一般是系统内存资源不足造成的(error 11在mysql中是资源临时不可用),解决方法是升级系统内存或者添加swap;

MySQL的内存消耗分为:
1)会话级别的内存消耗:如sort_buffer_size等,每个会话都会开辟一个sort_buffer_size来进行排序操作。
2)全局的内存消耗:例如:innodb_buffer_pool_size等,全局共享的内存段。会话级的内存消耗可能是一个原因。关于会话级的内存消耗解释如下:
read_buffer_size, sort_buffer_size, read_rnd_buffer_size, tmp_table_size这些参数在需要的时候才分配,操作后释放。
这些会话级的内存,不管使用多少都分配该size的值,即使实际需要远远小于这些size。
每个线程可能会不止一次需要分配buffer,例如子查询,每层都需要有自己的read_buffer,sort_buffer, tmp_table_size 等。
找到每次内存消耗峰值是不切实际的,因此建议可以用来衡量一下你实际修改一些变量值产生的反应,例如把 sort_buffer_size
从1MB增加到4MB并且在max_connections为1000 的情况下,内存消耗增长峰值并不是你所计算的3000MB而是30MB。

首先在/etc/my.cnf的mysqld配置区域下增加下面一句(根据机器本身的内存配置来设置下面这个参数值):

[root@mysql01 ~]# vim /etc/my.cnf
[mysqld]
.......
innodb_buffer_pool_size = 128M

然后开启Swap分区,重启Mysql服务。

开启SWAP分区的方法

1)创建用于交换分区的文件(block_size、number_of_block 大小可以根据机器本身配置情况进行自定义,)
[root@mysql01 ~]# dd if=/dev/zero of=/mnt/swap bs=1M count=40962)设置交换分区文件:
[root@mysql01 ~]# mkswap /mnt/swap3)立即启用交换分区文件
[root@mysql01 ~]# swapon /mnt/swap温馨提示:
如果在/etc/rc.local中有"swapoff -a",则需要修改为"swapon -a"4)设置开机时自启用 SWAP 分区:
需要修改文件 /etc/fstab 中的 SWAP 行,添加:
[root@mysql01 ~]# vim /etc/fstab
/mnt/swap swap swap defaults 0 05)修改swpapiness参数
在Linux系统中,可以通过查看/proc/sys/vm/swappiness内容的值来确定系统对SWAP分区的使用原则。
当swappiness内容的值为0时,表示最大限度地使用物理内存,物理内存使用完毕后,才会使用SWAP分区。
当swappiness内容的值为100时,表示积极地使用SWAP分区,并且把内存中的数据及时地置换到SWAP分区。查看修改前为0,需要在物理内存使用完毕后才会使用SWAP分区:
[root@mysql01 ~]# echo 0 > /proc/sys/vm/swappiness可以上面的方法临时修改此参数,假设我们配置为空闲内存少于10%时才使用SWAP分区,则操作方法如下:
[root@mysql01 ~]# echo 10 > /proc/sys/vm/swappiness若需要永久修改此配置,在系统重启之后也生效的话,可以修改 /etc/sysctl.conf 文件,并增加以下内容:
[root@mysql01 ~]# vim /etc/sysctl.conf
vm.swappiness=10
[root@mysql01 ~]# sysctl -p6)最后重启mysql服务
[root@mysql01 ~]# /etc/init.d/mysqld restart

关闭SWAP分区的方法

当系统出现内存不足时,开启 SWAP 可能会因频繁换页操作,导致 IO 性能下降。如果要关闭 SWAP,可以采用如下方法。1)free -m 查询 SWAP 分区设置:
[root@mysql01 ~]# free -m2)使用命令 swapoff 关闭 SWAP,比如:
[root@mysql01 ~]# swapoff /mnt/swap3)修改 /etc/fstab 文件,删除或注释相关配置,取消SWAP的自动挂载:
[root@mysql01 ~]# vim /etc/fsta
#/mnt/swap swap swap defaults 0 04)通过 free -m  确认 SWAP 已经关闭。
[root@mysql01 ~]# free -m5)swappiness 参数调整:
可以使用下述方法临时修改此参数,这里配置为 0%:
[root@mysql01 ~]# echo 0 >/proc/sys/vm/swappiness若需要永久修改此配置,在系统重启之后也生效的话,可以修改 /etc/sysctl.conf 文件,并增加以下内容:
[root@mysql01 ~]# vim /etc/sysctl.conf
vm.swappiness=0
[root@mysql01 ~]# sysctl -p

=========================================================
来看看曾经碰到的一个由于MySQL内存交换区引起的一场事故

 事故现象:公司的一个业务系统程序会调用大量的SQL,一天,发现MySQL的负载极其不稳定,尤其是Slave的负载有点猛,然后经过讨论准备再加一台Slave,。另加了一台Slave后,发现Slave的负载确实都回归正常了,本以为息事宁人,但是过了两个小时后,新添加的Slave的负载暴增至100以上!原来的Slave服务则显示正常。大概过了两个小时,新增加的Slave的负载又回归正常了,但是又过了两个小时后,负责又飙升至100以上!于是乎,赶紧Troubleshooting!过程如下:

1)考虑到新增的server,因为内存,CPU等硬件的配置和原来数据库的server都不一样(新增的Slave比原来的Slave的内存少了一半),必然配置参数的值也会不同。所以就从MySQl的配置文件查起,如:sort_buffer_size的大小(因为考虑到有许多SQL包含排序),join_buffer_size(用于连接的缓存的大小),max_connections(最大连接数,可是通过show processlist;发现也没有超过设置的值),innodb_buffer_pool_size(确认是否为物理内存的合适比例)等等。

2)使用free -m查看内存时,发现SWAP既然使用了500MB!通过vmsata,发现si和so的值不断的变化,可以肯定的是发生了内存交换。原来是SWAP捣的蛋!

内存交换区:当操作系统因为没有足够的内存而将一些虚拟内存写到磁盘就会发生内存交换。

内存交换对MySQL性能影响是极其糟糕的。它破坏了缓存在内存的目的,并且相对于使用很小的内存做缓存,使用交换区的性能更差。MySQL和存储引擎有很多算法来区别对待内存中的数据和硬盘上的数据,因为一般都是假设内存数据访问代价更低。

因为内存交换对用户进程不可见,MySQL(或存储引擎)并不知道数据实际上已经移动到磁盘,还会以为仍然在内存中呢。

结果会导致很差的性能。例如。若存储引擎认为数据依然在内存,可能觉得为"短暂"的内存操作锁定一个全局互斥变量(例如,InnoDB缓冲池Mutex)是OK的。如果这个操作实际上引起了硬盘I/O,直到I/O操作完成前任何操作都会被挂起。这意味着内存交换比直接做硬盘I/O操作还要糟糕。

在Linux上,可以用vmstat来监控内存交换。最好查看si和so列报告的内存交换I/O活动,这比看swapd列报告的交换区利用率更重要。我们都喜欢si和so列的值为0,并且一定要保证它们低于每秒10块。

可以通过正确地配置MySQL缓冲来解决大部分内存交换问题,但是有时操作系统的虚拟内存系统还是会决定交换MySQL内存。这通常发生在操作系统看到MySQL发出了大量I/O,因此尝试增加文件缓存来保存更多数据时。如果没有足够的内存,有些东西就必须交换出去,有些可能就是MySQL本身。

有些人主张完全禁用交换文件。这样做是很危险的,因为禁用内存交换就相当于给虚拟内存设置了一个不可动摇的限制。如果MySQL需要临时使用很大一块内存,或者有很耗内存的进程运行在同一台server上(如夜间的批量任务),MySQL可能会内存溢出,崩溃,或者被操作系统kill掉。

操作系统通常允许对虚拟内存和I/O进行一些控制。最基本的方法就是修改/proc/sys/vm/swappiness为一个很小的值,如0或1。这等同于告诉内核除非虚拟内存完全满了,否则不要使用交换区。下面是如何检查这个值的例子:

$ cat /proc/sys/vm/swappiness
60

这个值显示为60,这是默认的设置(范围是0~100)。对于服务器而言这是个很糟糕的默认值。服务器应该设置为0:

$ echo 0 > /proc/sys/vm/swappiness

另一个选项是修改存储引擎怎么读取和写入数据。使用innodb_flush_method=O_DIRECT,减轻I/O压力。DIRECT I/O并不缓存,因此操作系统并不能把MySQL视为增加文件缓存的原因。这个参数只对InnoDB有效。你也可以使用大页,不参与换入换出,这对MyISAM和InnoDB都有效。

另一个选择是使用MySQL的memlock配置项,可以把MySQL锁定在内存。这可以避免交换,但是也可能带来危险:如果没有足够的可锁定内存,MySQL在尝试分配更多内存时就会崩溃。

解决问题:

第一种方法:修改系统对虚拟内存的控制
[root@mysql01 ~]# echo 0 > /proc/sys/vm/swappiness#要想永久生效,将其配置写入/etc/sysctl.conf文件中
[root@mysql01 ~]# echo "vm.swappiness=0" >> /etc/sysctl.conf
#令其立即生效
[root@mysql01 ~]# sysctl -p第二种方法:修改innodb_flush_method参数
#注意innodb_flush_method是个全局变量,并且不支持动态修改,所以修改配置文件,重启MySQL
[root@mysql01 ~]# vim /etc/my.cnf
innodb_flush_method=O_DIRECT#添加其参数的配置,如果线上正在运行的数据库,就要先:
mysql> stop slave;#然后重启MySQL
[root@mysql01 ~]# /etc/init.d/mysqld restart

对于修改memlock配置项,不推荐。

结果:新增加的slave负载正常。swap的使用也降到了10MB的样子。

最后说下如何查看那个进程占用swap?

第一步:
[root@mysql01 ~]# top第二步:
按大写的O第三步:
输入小写字母p第四步:
回车

显示的结果如下图:

转载于:https://www.cnblogs.com/kevingrace/p/5570197.html

MySQL针对Swap分区的运维注意点相关推荐

  1. MySQL通用优化技巧 | Ucloud运维在线微信群分享

    MySQL通用优化技巧 | Ucloud运维在线微信群分享 2015-09-17  MySQL中文网 本文根据DevOps华南运维圈@UCloud微信群「大话运维」的嘉宾分享整理而成.「大话运维」将邀 ...

  2. mysql 二进制日志变化_MySQL运维之二进制日志

    MySQL二进制日志里保存会造成或可能造成数据变化的SQL语句.通过二进制日志可以完成如实时异地容灾备份.读写分离.数据恢复等功能.下面,我们一起来看看Mysql二进制日志. 开启bin-log日志 ...

  3. bind blz mysql_MySQ DBAL重点剖析课程 企业级MySQL系统安全与DBA运维日常事务管理 运维DBA必备宝典...

    MySQ DBAL重点剖析课程 企业级MySQL系统安全与DBA运维日常事务管理 运维DBA必备宝典 本资源由JAD资源网收集整理丨www.jiuandun.com 资源简介 MySQ DBAL重点剖 ...

  4. 本周四晚8点直播预告丨探秘MySQL极限,解锁核心运维关卡

    点击上方蓝色字关注我们~ 探秘MySQL极限,解锁核心运维关卡--3月3日20:00 根据 DB-engine 流行度显示,MySQL 是最流行的开源关系型数据库管理系统,在 WEB 应用方面,是最好 ...

  5. Mysql基于GTID复制模式-运维小结 (完整篇)

    先来看mysql5.6主从同步操作时遇到的一个报错: mysql> change master to master_host='192.168.10.59',master_user='repli ...

  6. mysql cnf参数_系统运维|MySQL my.cnf参数配置优化详解

    本配置文件针对Dell R710,双至强E5620.16G内存的硬件配置.CentOS 5.6 64位系统,MySQL 5.5.x 稳定版.适用于日IP 50-100w,PV 100-300w的站点, ...

  7. centos7parted分区_CentOS7 运维 - 磁盘管理与文件系统 | 超详细 | 附挂载教程及错误排查 | parted超大磁盘分区教程...

    硬盘结构 硬盘的物理结构 盘头:硬盘有多个盘片,每盘片两面 磁头:每面一个磁头 硬盘的数据结构 扇区:盘片被分为多个扇形区域,每个扇区存放512字节的数据,是硬盘的最小存储单位 磁道:同一盘片不同半径 ...

  8. MySQL和Linux试题_Linux运维必会的MySql题之(一)

    如何启动MySql服务 /etc/init.d/mysqld start service mysqld start Centos7.x 系统 systemctl start mysqld 检测端口是否 ...

  9. mysql中的时间函数---运维常用

    一.查看当前时间 now函数 mysql> select now(); +---------------------+ | now() | +---------------------+ | 2 ...

最新文章

  1. 微服务,微架构[五]之springboot读取properties文件
  2. 深入使用XMemcached
  3. xcode6是否导入framework
  4. 开源项目几点心得,Java架构必会几大技术点
  5. Linux 进程号 端口号 互找
  6. django 实现linux运维管理平台
  7. Win32汇编---控件的超类化感想
  8. 【echarts 中国地图】vue实现中国地图,省份居中china.json文件下载
  9. 无光驱安装redhat企业版
  10. 1200PLC和Modbus485主站DCS系统通讯
  11. Mybatis如何实现分页
  12. Mac下载安装配置maven
  13. 深度残差学习的图像识别
  14. 【Unity实战100例】Unity自定义修改按键功能
  15. Guitar Pro里的渐强渐弱符号
  16. peda、Pwngdb、pwndbg的安装及避坑指南
  17. linux 网卡对应网口查看方式
  18. css权重机制,Css权重计算方式
  19. 关于开环、闭环和半闭环系统
  20. 如何用女生的几张的照片做出一张能感动她的照片

热门文章

  1. class文件打成jar包
  2. TomcatServlet笔记
  3. SRC漏洞挖掘之偏门资产收集篇
  4. 微服务架构--链路追踪(Nginx篇)
  5. Python面向对象、魔法方法
  6. 2016校招腾讯研发岗笔试题---递归法求解格雷码
  7. Failed to load sql modules into the database cluster during PostgreSQL Installation
  8. JSR94(Java Rule Engine)
  9. 活用变量字符串${var%%.*}
  10. 《需求设计:构建用户想要和需要的产品》——第1章 情境驱动设计入门1.1 对需求进行设计...