性能调优之MySQL篇四:MySQL配置定位以及优化

1、CPU最大性能模式

cpu利用特色

  • 5.1 最高可用4个核node

  • 5.5 最高可用24核mysql

  • 5.6 最高可用64核心算法

  • 一次query对应一个逻辑CPUsql

你仔细检查的话,有些服务器上会有的一个有趣的现象:你cat /proc/cpuinfo时,会发现CPU的频率居然跟它标称的频率不同:数据库

#cat /proc/cpuinfo 
processor : 5
model name : Intel(R) Xeon(R) CPU E5-2620 0 @2.00GHz
...
cpu MHz : 1200.000

这个是Intel E5-2620的CPU,他是2.00G * 24的CPU,可是,咱们发现第5颗CPU的频率为1.2G缓存

缘由:其实都源于CPU最新的技术:节能模式。操做系统和CPU硬件配合,系统不繁忙的时候,为了节约电能和下降温度,它会将CPU降频。这对环保人士和抵制地球变暖来讲是一个福音,可是对MySQL来讲,多是一个灾难。 安全

为了保证MySQL可以充分利用CPU的资源,建议设置CPU为最大性能模式,这个设置能够在BIOS和操做系统中设置bash

2、关闭numa

非一致存储访问结构 (NUMA : Non-Uniform Memory Access) 也是最新的内存管理技术。它和对称多处理器结构 (SMP : Symmetric Multi-Processor) 是对应的。简单的队别如图:服务器

可是咱们能够直观的看到:SMP访问内存的都是代价都是同样的;可是在NUMA架构下,本地内存的访问和非本地内存的访问代价是不同的。对应的根据这个特性,操做系统上,咱们能够设置进程的内存分配方式。目前支持的方式包括:架构

--interleave=nodes 
--membind=nodes 
--cpunodebind=nodes 
--physcpubind=cpus 
--localalloc 
--preferred=node

简而言之,就是说,你能够指定内存在本地分配,在某几个CPU节点分配或者轮询分配。除非是设置为--interleave=nodes轮询分配方式,即内存能够在任意NUMA节点上分配这种方式之外。

其余的方式就算其余NUMA节点上还有内存剩余,Linux也不会把剩余的内存分配给这个进程,而是采用SWAP的方式来得到内存。有经验的系统管理员或者DBA都知道SWAP致使的数据库性能降低 ,因此最简单的方法,仍是关闭掉这个特性

关闭特性的方法,分别有:

  • 能够从BIOS设置关闭

  • 启动MySQL的时候,关闭NUMA特性 numactl --interleave=all  mysqld &

  • OS内核,启动时设置numa=off

  • 在操做系统中关闭,能够直接在/etc/grub.conf的kernel行最后添加numa=off,以下所示

kernel /vmlinuz-2.6.32-220.el6.x86_64 ro root=/dev/mapper/VolGroup-root rd_NO_LUKS LANG=en_US.UTF-8 rd_LVM_LV=VolGroup/root rd_NO_MD quiet SYSFONT=latarcyrheb-sun16 rhgb crashkernel=auto rd_LVM_LV=VolGroup/swap rhgb crashkernel=auto quiet KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM  numa=off

设置vm.zone_reclaim_mode=0尽可能回收内存

3、关闭vm.swappiness

vm.swappiness是操做系统控制物理内存交换出去的策略。它容许的值是一个百分比的值,最小为0,最大运行100,该值默认为60

vm.swappiness设置为0表示尽可能少swap,100表示尽可能将inactive的内存页交换出去。 

当内存基本用满的时候,系统会根据这个参数来判断是把内存中不多用到的inactive 内存交换出去,仍是释放数据的cache。cache中缓存着从磁盘读出来的数据,根据程序的局部性原理,这些数据有可能在接下来又要被读取;inactive 内存顾名思义,就是那些被应用程序映射着,可是“长时间”不用的内存。 

咱们能够查看inactive的内存的数量:

[root@locahost ~]# vmstat -an 1 
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
 r  b   swpd   free  inact active   si   so    bi    bo   in   cs us sy id wa st
 0  0  61432 1533944 1553788 3190400    0    0     9   216    0    0  5  2 88  4  0
 0  0  61432 1533564 1553900 3190568    0    0     0   120  616  349  2  1 97  1  0
 1  0  61432 1533068 1553844 3191096    0    0     0  5748 1604  455  1  1 95  3  0
 2  1  61432 1531952 1553812 3191984    0    0   172   700 1033  416  2  1 74 23  0

[root@locahost ~]# cat /proc/meminfo | grep -i inact 
Inactive:        1557236 kB
Inactive(anon):   279888 kB
Inactive(file):  1277348 kB

Linux中,内存可能处于三种状态:free,active和inactive

Linux Kernel在内部维护了不少LRU列表用来管理内存,好比LRU_INACTIVE_ANON, LRU_ACTIVE_ANON, LRU_INACTIVE_FILE , LRU_ACTIVE_FILE, LRU_UNEVICTABLE。其中LRU_INACTIVE_ANON, LRU_ACTIVE_ANON用来管理匿名页,LRU_INACTIVE_FILE , LRU_ACTIVE_FILE用来管理page caches页缓存。系统内核会根据内存页的访问状况,不定时的将活跃active内存被移到inactive列表中,这些inactive的内存能够被交换到swap中去。 

MySQL,特别是InnoDB管理内存缓存,它占用的内存比较多,不常常访问的内存也会很多,这些内存若是被Linux错误的交换出去了,将浪费不少CPU和IO资源。 InnoDB本身管理缓存,cache的文件数据来讲占用了内存,对InnoDB几乎没有任何好处。 

因此,咱们在MySQL的服务器上最好设置vm.swappiness=0。

咱们能够经过在sysctl.conf中添加一行: 

echo "vm.swappiness = 0" >>/etc/sysctl.conf

4、文件系统

建议在文件系统的mount参数上加上noatime,nobarrier两个选项

用noatime mount的话,文件系统在程序访问对应的文件或者文件夹时,不会更新对应的access time。通常来讲,Linux会给文件记录了三个时间,change time, modify time和access time。 
咱们能够经过stat来查看文件的三个时间: 

[root@localhost ~]# stat mysql-test.sh 
  File: `mysql-test.sh'
  Size: 970             Blocks: 8          IO Block: 4096   regular file
Device: ca01h/51713d    Inode: 33883111    Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2015-12-16 19:55:58.962535495 +0800
Modify: 2015-12-11 09:15:38.410196493 +0800
Change: 2015-12-11 09:15:38.493196460 +0800
  • access time指文件最后一次被读取的时间

  • modify time指的是文件的文本内容最后发生变化的时间

  • change time指的是文件的inode最后发生变化(好比位置、用户属性、组属性等)的时间

通常来讲,文件都是读多写少,并且咱们也不多关心某一个文件最近什么时间被访问了。因此,咱们建议采用noatime选项,这样文件系统不记录access time,避免浪费资源

如今的不少文件系统会在数据提交时强制底层设备刷新cache,避免数据丢失,称之为write barriers。可是,其实咱们数据库服务器底层存储设备要么采用RAID卡,RAID卡自己的电池能够掉电保护;要么采用Flash卡,它也有自我保护机制,保证数据不会丢失。因此咱们能够安全的使用nobarrier挂载文件系统。设置方法以下: 对于ext3, ext4和 reiserfs文件系统能够在mount时指定barrier=0;对于xfs能够指定nobarrier选项

文件系统上还有一个提升IO的优化万能钥匙,那就是deadline

在Flash技术以前,咱们都是使用机械磁盘存储数据的,机械磁盘的寻道时间是影响它速度的最重要因素,直接致使它的每秒可作的IO(IOPS)很是有限,为了尽可能排序和合并多个请求,以达到一次寻道可以知足屡次IO请求的目的,Linux文件系统设计了多种IO调度策略,已适用各类场景和存储设备。 

Linux的IO调度策略包括:Deadline scheduler,Anticipatory scheduler,Completely Fair Queuing(CFQ),NOOP

CFQ是Linux内核2.6.18以后的默认调度策略,它声称对每个 IO 请求都是公平的,这种调度策略对大部分应用都是适用的。可是若是数据库有两个请求,一个请求3次IO,一个请求10000次IO,因为绝对公平,3次IO的这个请求都须要跟其余10000个IO请求竞争,可能要等待上千个IO完成才能返回,致使它的响应时间很是慢。而且若是在处理的过程当中,又有不少IO请求陆续发送过来,部分IO请求甚至可能一直没法获得调度被“饿死”。而deadline兼顾到一个请求不会在队列中等待过久致使饿死,对数据库这种应用来讲更加适用

CFQ与Deadline,NOOP性能差别很小,可是一旦有大的连续IO,CFQ可能会形成小IO的响应延时增长,因此数据库环境建议修改成deadline算法,表现更稳定。咱们的环境统一使用deadline算法。

IO调度算法都是基于磁盘设计,因此减小磁头移动是最重要的考虑因素之一,可是使用Flash存储设备以后,再也不须要考虑磁头移动的问题,可使用NOOP算法。NOOP的含义就是NonOperation,意味着不会作任何的IO优化,彻底按照请求来FIFO的方式来处理IO。

减小预读:/sys/block/sdb/queue/read_ahead_kb,默认128,调整为16

增大队列:/sys/block/sdb/queue/nr_requests,默认128,调整为512

实时设置,咱们能够经过

echo deadline >/sys/block/sda/queue/scheduler

咱们也能够直接在/etc/grub.conf的kernel行最后添加elevator=deadline来永久生效

5、RAID优化

关闭读cache:RAID卡上的cache容量有限,咱们选择direct方式读取数据,从而忽略读cache。

关闭预读:RAID卡的预读功能对于随机IO几乎没有任何提高,因此将预读功能关闭。

关闭磁盘cache:通常状况下,若是使用RAID,系统会默认关闭磁盘的cache,也能够用命令强制关闭。

以上设置均可以经过RAID卡的命令行来完成

开启BBWC

RAID卡都有写cache(Battery Backed Write Cache),写cache对IO性能的提高很是明显,由于掉电会丢失数据,因此必须由电池提供支持。电池会按期充放电,通常为90天左右,当发现电量低于某个阀值时,会将写cache策略从writeback置为writethrough,至关于写cache会失效,这时若是系统有大量的IO操做,可能会明显感受到IO响应速度变慢。目前,新的RAID卡内置了flash存储,掉电后会将写cache的数据写入flash中,这样就能够保证数据永不丢失,但依然须要电池的支持。

解决方案有两种:1.人工触发充放电,能够选择在业务低谷时作,下降对应用的影响;2.设置写cache策略为force write back,即便电池失效,也保持写cache策略为writeback,这样存在掉电后丢失数据的风险。

6、Flashcache

建立flashcache:flashcache_create -b 4k cachedev /dev/sdc /dev/sdb

指定flashcache的block大小与Percona的page大小相同。

Flashcache参数设置:

flashcache.fast_remove = 1:打开fast remove特性,关闭机器时,无需将cache中的脏块写入磁盘
flashcache.reclaim_policy = 1:脏块刷出策略,0:FIFO,1:LRU
flashcache.dirty_thresh_pct = 90:flashcache上每一个hash set上的脏块阀值
flashcache.cache_all = 1:cache全部内容,能够用黑名单过滤
flashecache.write_merge = 1:打开写入合并,提高写磁盘的性能

7、IOPS

磁盘寻道能力(磁盘I/O),以目前高转速SCSI硬盘(7200转/秒)为例,这种硬盘理论上每秒寻道7200次,这是物理特性决定的,没有办法改变。 MySQL每秒钟都在进行大量、复杂的查询操做,对磁盘的读写量可想而知。因此,一般认为磁盘I/O是制约MySQL性能的最大因素之一,对于日均访问量 在100万PV以上的Discuz!论坛,因为磁盘I/O的制约,MySQL的性能会很是低下!解决这一制约因素能够考虑如下几种解决方案:  使用RAID-0+1磁盘阵列,注意不要尝试使用RAID-5,MySQL在RAID-5磁盘阵列上的效率不会像你期待的那样快

innodb_page_size:若是使用fusionio,4K的性能最好;使用SAS磁盘,设置为8K。若是全表扫描不少,能够设置为16K。比较小的page size,能够提高cache的命中率。
innodb_adaptive_checkpoint:若是使用fusionio,设置为3,提升刷新频率到0.1秒;使用SAS磁盘,设置为2,采用estimate方式刷新脏页。
innodb_io_capacity:根据IOPS能力设置,使用fuionio能够设置10000以上。
innodb_flush_neighbor_pages = 0:针对fusionio或者SSD,由于随机IO足够好,因此关闭此功能。
innodb_flush_method=ALL_O_DIRECT:公版的MySQL只能将数据库文件读写设置为DirectIO,对于Percona能够将log和数据文件设置为direct方式读写。可是我不肯定这个参数对于innodb_flush_log_at_trx_commit的影响,
innodb_read_io_threads = 1:设置预读线程设置为1,由于线性预读的效果并不明显,因此无需设置更大。
innodb_write_io_threads = 16:设置写线程数量为16,提高写的能力。
innodb_fast_checksum = 1:开启Fast checksum特性。
相关文章
相关标签/搜索