MySQL如何避免使用Linux的swap分区而提升读写性能

MySQL如何避免使用Linux的swap分区而提升读写性能

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

首先我们要了解点基础的东西,比如说为什么会产生swap。假设我们的物理内存是16G,swap是4G。如果MySQL本身已经占用了12G物理 内存,而同时其他程序或者系统模块又需要6G内存,这时候操作系统就可能把MySQL所拥有的一部分地址空间映射到swap上去。

cp一个大文件,或用mysqldump导出一个很大的数据库的时候,文件系统往往会向Linux申请大量的内存作为cache,一不小心就会导致L使用swap。这个情景比较常见,以下是最简单的三个调整方法:

1、/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
这个参数会强迫mysqld进程的地址空间一直被锁定在物理内存上,对于os来说是非常霸道的一个要求。必须要用root帐号来启动MySQL才能生效。

还有一个比较复杂的方法,指定MySQL使用大页内存(Large Page)。Linux上的大页内存是不会被换出物理内存的,和memlock有异曲同工之妙。具体的配置方法可以参 考:http://harrison-fisk.blogspot.com/2009/01/enabling-innodb-large-pages- on-linux.html

之前介绍了MySQL如何避免使用swap的四个方法。这里需要补充一下原理和实现机制,对于Linux api不感兴趣的同学可以直接跳过。

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

二、Linux提供的几个api
1、mlockall()和munlockall()
这一对函数,可以让调用者的地址空间常驻物理内存,也可以在需要的时候将此特权取消。mlockall()的flag位可以是MCL_CURRENT和 MCL_FUTURE的任意组合,分别代表了“保持已分配的地址空间常驻物理内存”和“保持未来分配的地址空间常驻物理内存”。对于Linux来说,这对 函数是非常霸道的,只有root用户才有权限调用。

2、shmget()和shmat()
这一对函数,可以向操作系统申请使用大页内存(Large Page)。大页内存的特点是预分配和永驻物理内存,因为使用了共享内存段的方式,page table有可能会比传统的小页分配方式更小。对于多进程共享内存的程序(比如ORACLE),大页内存能够节省很多page table开销;而对于MySQL来说,性能和资源开销都没有显著变化,好处就在于减少了内存地址被映射到swap上的可能。至于为什么是减少,而不是完全避免,之后再讲解。

3、O_DIRECT和posix_memalign()
以上两个方法都不会减少内存的使用量,调用者的本意是获取更高的系统特权,而不是节约系统资源。O_DIRECT是一种更加理想化的方式,通过避免 double buffer,节省了文件系统cache的开销,最终减少swap的使用率。O_DIRECT是Linux IO调度相关的标志,在open函数里面调用。通过O_DIRECT标志打开的文件,读写都不会用到文件系统的cache。传统的数据库(ORACLE、MySQL)基本都有O_DIRECT相关的开关,在提高性能的同时,也减少了内存的使用。至于posix_memalign(),是用来申请对齐的内存地址的。只有用posix_memalign()申请的内存地址,才能用来读写O_DIRECT模式下的文件描述符。

4、madvise()和fadvise()
这对函数也是比较温和的,可以将调用者对数据访问模式的预期传递给Linux,以期得到更好的性能。
我们比较感兴趣的是MADV_DONTNEED和FADV_NOREUSE这两个flag。前者会建议Linux释放指定的内存区域,而后者会建议文件系统释放指定文件所占用的cache。

三、MySQL内存使用相关的一些代码
1、memlock
在MySQL的源码目录里面查询memlock,可以知道这个参数的作用是使MySQL调用mlockall()。在源码里面匹配可以得知NDB、MyISAM和 mysqld都调用了mlockall()。NDB是可以独立于MySQL而存在的存储引擎,此处按下不表。mysqld调用mlockall()的方式 有点出乎意料,在init_server_components()函数里传给mlockall()的flag是MCL_CURRENT,也就是说之后申 请的内存一概不用锁住。再看看MyISAM的调用顺序是:mlockall() <- lock_memory() <- mi_repair(),MyISAM只有修复的时候会调用mlockall()函数。

2、large-pages
根据Linux的内核文档,大页内存有两种方法可以用到:一种是创建hugetlb类型的文件,并将它mmap到程序的内存地址里面,然后进行正常的读写 操作。另外一种是之前说到的shmget()+shmat(),也正是MySQL采用的方式。在MySQL的源码目录里面匹配shmget,可以发现 BDB、NDB、InnoDB、MyISAM都调用了这个函数。接着看一下比较常用的InnoDB和MyISAM引擎。
在InnoDB里面可以找到os_mem_alloc_large()调用了shmget(),而调用os_mem_alloc_large()的函数只 有buf_pool_init()——InnoDB Buffer Pool的初始化函数。根据观察得到的结论是,InnoDB会根据配置参数在Buffer Pool里面使用大页内存,Redo log貌似就没有这个待遇了。
对于MyISAM,在storage层级的代码里面找不到对shmget()的直接调用。这是因为MyISAM是MySQL的原生存储引擎,很多函数存放 在上一层的mysys目录里面。通过搜索shmget(),我们可以找到MyISAM的调用顺序是这样的:shmget() <- my_large_malloc_int() <- my_large_malloc() <- init_key_cache()。也就是说MyISAM只有索引缓存用到了大页内存,这是很容易理解,因为MyISAM的数据是直接扔给文件系统做缓存 的,没法使用大页内存。

3、innodb_flush_method
O_DIRECT是BDB、NDB、InnoDB特有的参数,在这里只讨论InnoDB这个比较常见的引擎。在InnoDB的源码目录里面匹配 O_DIRECT,很容易找到一个叫做os_file_set_nocache()的函数,而这个函数作用是将文件的打开方式改为O_DIRECT模式。 再跟踪一下,会发现只有os_file_create()函数调用了os_file_set_nocache()。虽然函数名里面还有create,实际 上os_file_create()会根据传入参数的不同,选择打开或者新建一个文件。同时os_file_create()还会根据MySQL的配置, 来调用os_file_set_nocache()关闭文件系统的相应cache。在os_file_create()函数里面有如下一段代码:
/* We disable OS caching (O_DIRECT) only on data files */
if (type != OS_LOG_FILE &&
srv_unix_file_flush_method == SRV_UNIX_O_DIRECT)
{
os_file_set_nocache(file, name, mode_str);
}
这段代码的意思是,只有InnoDB的数据文件有资格使用O_DIRECT模式,Redo log是不能使用的。

以上的分析基于5.0.85版本的原版MySQL,InnoDB是Innobase。
版本不同情况下可能会有一些出入,欢迎参与讨论。

参考文献:
Virtual memory@wiki
All about Linux swap space
HugeTLB – Large Page Support in the Linux Kernel
Page table@wiki

来源:http://www.taobaodba.com/html/552_mysql_avoid_swap.html

http://www.taobaodba.com/html/554_mysql_avoid_swap_2.html

永久链接 : http://www.ha97.com/4201.html

时间: 2024-08-25 08:56:21

MySQL如何避免使用Linux的swap分区而提升读写性能的相关文章

设置和修改Linux的swap分区大小

在Linux编译gcc时,遇到编译错误,究其根源是因为内存不足,这时通过修改swap大小解决了问题 相关操作如下: 1. 查看当前分区情况free -m 2. 增加 swap 大小, 2G 左右dd if=/dev/zero of=/var/swap bs=1024 count=2048000 3. 设置交换文件mkswap /var/swap 4. 立即激活启用交换分区swapon /var/swap 5. 添加系统引导时自启动运行vi /etc/fstab 添加一行/var/swap swa

linux增加swap分区大小

  linux增加swap分区大小 2016-08-2 13:54:58 分类: LINUX 懂得Linux的都知道,标准的Linux安装,SWAP分区是内存的两倍大小,如果增加了内存条,那SWAP分区也要增加   如果增加1G内存,SWAP分区就要增加2G   一.决定修改swap大小,首先在空间合适处创建用于分区的swap文件:如/swap1       #dd if=/dev/zero of=/swap1 bs=1M count=2048   if 表示 infile,of 表示outfi

linux初学者-swap分区篇

linux初学者-swap分区篇 swap是虚拟内存,是在硬盘中分区一块区域,当内存占满但是又急迫需要时临时当作内存使用,使用效率低于内存.本文将对linux系统中swap分区的建立做一个简要介绍. swap分区本质也是一个分区,所以在做swap分区之前先要进行普通分区,如下图所示,分区完成后先不保存退出,输入"t"来改变分区功能id,选择需要进行修改的分区后,输入ID号来改变分区功能标识,dos分区记录方式的swap分区标识编号为82,而gpt则为14.完成后保存退出. 输入命令&q

Linux下swap分区多大才合适的问题探讨

说明: 1.这个话题在每个Linux发行版中都各不相同,且在当下内存硬盘的时代下,再组个磁盘阵列之后速度相当. 2.我觉得硬盘大的情况下,有多大搞多大,我只要控制内存的使用率在99%时才使用swap,且如果是阵列后的内存硬盘,那基本性能不会差到哪里去. 3.还有一种情况,比如数据库服务器(MySQL)这些,与一些应用服务器,还有当单纯的缓存服务器(Redis)这些配置swap都不一样,比如数据库服务器和缓存服务器这些就不建议使用swap分区,比如要绝对100%使用内存,并且内存在256G以上.而

Azure Linux VM Swap 分区

默认情况下,Windows Azure上的Linux VM是没有Swap分区的.下面我们以Ubuntu为例,为Windows Azure上的Linux虚拟机创建Swap分区. Windows Azure会为每个虚拟机分配一个临时盘,这个临时盘在Windows Server操作系统中是[D:]盘,在Linux中是/dev/sdb1.值得一提的是,在D系列的虚拟机中,临时盘是SSD存储.显然,临时盘是创建Swap分区的好地方.既然是临时盘,就千万不要把应用和数据存储在上面,否则数据丢了就只能自己哭了

linux 新建swap 分区

阿里云主机一般默认不带swap分区,需要手工新建. 1)查看磁盘情况: [[email protected]_app ~]# fdisk -l Disk /dev/xvda: 21.5 GB, 21474836480 bytes 255 heads, 63 sectors/track, 2610 cylinders Units = cylinders of 16065 * 512 = 8225280 bytes Sector size (logical/physical): 512 bytes

。linux中swap分区

1.swap分区的最重要的作用是防止网站流量突然增大而导致系统分配内存不够用而死机. 2.使用swap交换分区,会使服务器的性能降低很多,导致访问速度变慢. 3.交换分区.我们如果没有足够的内存,也许就不能运行某些大型的软件,解决的办法是在硬盘上划出一个区域来当作临时的内存,好像内存变大了.Windows操作系统把这个区域叫做虚拟内存,Linux把它叫做交换分区swap.

Linux增加swap分区的方法

1.新建磁盘分区作为swap分区2.用文件作为swap分区 (操作更简单,我更常用) 一.新建磁盘分区作为swap分区 1. # swapoff -a #停止所有的swap分区 2. 用fdisk命令(例:# fdisk /dev/sdb)对磁盘进行分区,添加swap分区,新建分区,在fdisk中用"t"命令将新添的分区id改为82(Linux swap类型),最后用w将操作实际写入硬盘(没用w之前的操作是无效的). 3. # mkswap /dev/sdb2 #格式化swap分区,这

Linux 之 swap分区创建与管理

swap分区创建与管理 1.查看swap分区 [[email protected] ~]# free -h total used free shared buffers cached Mem: 2.0G 1.0G 944M 1.5M 265M 341M -/+ buffers/cache: 454M 1.5G Swap: 4.0G 0B 4.0G #swap分区大小 [[email protected] ~]# fdisk -l Disk /dev/sda: 53.7 GB, 536870912