Nowadays, most of the environments where MySQL runs are on Linux. How to optimize MySQL on the Linux operating system, here are some common and simple strategies. These methods all help improve MySQL performance.
Stop chatting and get to the point.
1. CPU
Let’s start with the CPU.
If you check carefully, there is an interesting phenomenon on some servers: when you cat /proc/cpuinfo, you will find that the CPU frequency is different from its nominal frequency:
#cat /proc/cpuinfo processor : 5 model name : Intel(R) Xeon(R) CPU E5-2620 0 @2.00GHz ... cpu MHz : 1200.000
This is Intel E5-2620 CPU, it is a 2.00G * 24 CPU, but we found that the frequency of the fifth CPU is 1.2G.
What is the reason for this?
These are actually derived from the latest technology of CPU: energy-saving mode. The operating system cooperates with the CPU hardware. When the system is not busy, it will reduce the frequency of the CPU in order to save power and reduce temperature. This is a boon for environmentalists and the fight against global warming, but for MySQL, it could be a disaster.
In order to ensure that MySQL can make full use of CPU resources, it is recommended to set the CPU to maximum performance mode. This setting can be set in the BIOS and operating system. Of course, setting this option in the BIOS is better and more thorough. Due to the differences between various BIOS types, setting the CPU to maximum performance mode varies greatly, so we will not show you how to set it up here.
2. Memory
Then let’s look at the memory and see what we can optimize.
i) Let’s take a look at numa first
Non-Uniform Memory Access Structure (NUMA: Non-Uniform Memory Access) is also the latest memory management technology. It corresponds to the symmetric multi-processor architecture (SMP: Symmetric Multi-Processor).
The cost of SMP accessing memory is the same; but under the NUMA architecture, the cost of local memory access and non-local memory access are different. Correspondingly, according to this feature, on the operating system, we can set the memory allocation method of the process. Currently supported methods include:
–interleave=nodes
–membind=nodes
–cpunodebind=nodes
–physcpubind=cpus
–localalloc
–preferred=node
In short, that is, you can specify where the memory is Local allocation, allocation on certain CPU nodes or polling allocation. Unless the –interleave=nodes polling allocation mode is set, memory can be allocated on any NUMA node. In other ways, even if there is memory remaining on other NUMA nodes, Linux will not allocate the remaining memory to this process, but will use SWAP to obtain memory. Experienced system administrators or DBAs all know how destructive database performance degradation caused by SWAP can be.
So the easiest way is to turn off this feature.
Methods to turn off the feature include: You can temporarily turn off this feature from the BIOS, operating system, or when starting the process.
a) Due to the differences between various BIOS types, how to turn off NUMA varies greatly, so we will not show you how to set it up here.
b) To turn it off in the operating system, you can directly add numa=off at the end of the kernel line in /etc/grub.conf, as shown below:
kernel /vmlinuz-2.6.32-220.el6.x86_64 ro root=/dev/mapper/VolGroup-root rd_NO_LUKS.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
In addition, you can set vm.zone_reclaim_mode=0 to try to reclaim memory.
c) When starting MySQL, turn off the NUMA feature:
numactl --interleave=all mysqld &
Of course, the best way is to turn it off in the BIOS.
ii) Let’s look at vm.swappiness again.
vm.swappiness is the operating system’s strategy for controlling physical memory swapping. The allowed values are a percentage, with a minimum of 0 and a maximum of 100. The value defaults to 60. Setting vm.swappiness to 0 means to swap as little as possible, and 100 means to swap out inactive memory pages as much as possible.
Specifically: When the memory is basically full, the system will use this parameter to determine whether to swap out the inactive memory that is rarely used in the memory, or to release the data cache. The cache caches data read from the disk. According to the locality principle of the program, these data may be read again in the future; inactive memory, as the name suggests, is those that are mapped by the application but are not used for a "long time" Memory.
We can use vmstat to see the amount of inactive memory:
#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 1 0 0 27522384 326928 1704644 0 0 0 153 11 10 0 0 100 0 0 0 0 0 27523300 326936 1704164 0 0 0 74 784 590 0 0 100 0 0 0 0 0 27523656 326936 1704692 0 0 8 8 439 1686 0 0 100 0 0 0 0 0 27524300 326916 1703412 0 0 4 52 198 262 0 0 100 0 0
You can see more detailed information through /proc/meminfo:
#cat /proc/meminfo | grep -i inact Inactive: 326972 kB Inactive(anon): 248 kB Inactive(file): 326724 kB
这里我们对不活跃inactive内存进一步深入讨论。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
并使用sysctl -p来使得该参数生效。
三、文件系统
最后,我们看一下文件系统的优化
i)我们建议在文件系统的mount参数上加上noatime,nobarrier两个选项。
用noatime mount的话,文件系统在程序访问对应的文件或者文件夹时,不会更新对应的access time。一般来说,Linux会给文件记录了三个时间,change time, modify time和access time。
我们可以通过stat来查看文件的三个时间:
stat libnids-1.16.tar.gz File: `libnids-1.16.tar.gz' Size: 72309 Blocks: 152 IO Block: 4096 regular file Device: 302h/770d Inode: 4113144 Links: 1 Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root) Access : 2008-05-27 15:13:03.000000000 +0800 Modify: 2004-03-10 12:25:09.000000000 +0800 Change: 2008-05-27 14:18:18.000000000 +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选项。
ii)文件系统上还有一个提高IO的优化万能钥匙,那就是deadline。
在Flash技术之前,我们都是使用机械磁盘存储数据的,机械磁盘的寻道时间是影响它速度的最重要因素,直接导致它的每秒可做的IO(IOPS)非常有限,为了尽量排序和合并多个请求,以达到一次寻道能够满足多次IO请求的目的,Linux文件系统设计了多种IO调度策略,已适用各种场景和存储设备。
Linux的IO调度策略包括:Deadline scheduler,Anticipatory scheduler,Completely Fair Queuing(CFQ),NOOP。每种调度策略的详细调度方式我们这里不详细描述,这里我们主要介绍CFQ和Deadline,CFQ是Linux内核2.6.18之后的默认调度策略,它声称对每一个 IO 请求都是公平的,这种调度策略对大部分应用都是适用的。但是如果数据库有两个请求,一个请求3次IO,一个请求10000次IO,由于绝对公平,3次IO的这个请求都需要跟其他10000个IO请求竞争,可能要等待上千个IO完成才能返回,导致它的响应时间非常慢。并且如果在处理的过程中,又有很多IO请求陆续发送过来,部分IO请求甚至可能一直无法得到调度被“饿死”。而deadline兼顾到一个请求不会在队列中等待太久导致饿死,对数据库这种应用来说更加适用。
实时设置,我们可以通过
echo deadline >/sys/block/sda/queue/scheduler
来将sda的调度策略设置为deadline。
我们也可以直接在/etc/grub.conf的kernel行最后添加elevator=deadline来永久生效。
总结
CPU方面
关闭电源保护模式
内存:
vm.swappiness = 0
关闭numa
文件系统:
用noatime,nobarrier挂载系统
IO调度策略修改为deadline。