現在mysql運作的大部分環境都是在linux上的,如何在linux作業系統上根據mysql進行優化,我們這裡給出一些通用簡單的政策。這些方法都有助于改進mysql的性能。
閑話少說,進入正題。
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5GcuUWaqVmZ5BXd3Z2d1UDc5EnMxATN1EzLchjMvw1NwQTMwIzLc1WdixWYvwFduVWboNWY0RXYvwVY0FGZvwVZt5CevJWcu42Y4VnbpxWLuR2Lc9CX6MHc0RHaiojIsJye.png)
<a target="_blank"></a>
首先從cpu說起。
你仔細檢查的話,有些伺服器上會有的一個有趣的現象:你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和作業系統中設定,當然,在bios中設定該選項更好,更徹底。由于各種bios類型的差別,設定為cpu為最大性能模式千差萬别,我們這裡就不具體展示怎麼設定了。
然後我們看看記憶體方面,我們有哪些可以優化的。
非一緻存儲通路結構 (numa : non-uniform memory access) 也是最新的記憶體管理技術。它和對稱多處理器結構 (smp : symmetric multi-processor) 是對應的。簡單的隊别如下:
如圖所示,詳細的numa資訊我們這裡不介紹了。但是我們可以直覺的看到:smp通路記憶體的都是代價都是一樣的;但是在numa架構下,本地記憶體的通路和非 本地記憶體的通路代價是不一樣的。對應的根據這個特性,作業系統上,我們可以設定程序的記憶體配置設定方式。目前支援的方式包括:
--interleave=nodes
--membind=nodes
--cpunodebind=nodes
--physcpubind=cpus
--localalloc
--preferred=node
簡而言之,就是說,你可以指定記憶體在本地配置設定,在某幾個cpu節點配置設定或者輪詢配置設定。除非 是設定為--interleave=nodes輪詢配置設定方式,即記憶體可以在任意numa節點上配置設定這種方式以外。其他的方式就算其他numa節點上還有内 存剩餘,linux也不會把剩餘的記憶體配置設定給這個程序,而是采用swap的方式來獲得記憶體。有經驗的系統管理者或者dba都知道swap導緻的資料庫性能 下降有多麼坑爹。
是以最簡單的方法,還是關閉掉這個特性。
關閉特性的方法,分别有:可以從bios,作業系統,啟動程序時臨時關閉這個特性。
a) 由于各種bios類型的差別,如何關閉numa千差萬别,我們這裡就不具體展示怎麼設定了。
b) 在作業系統中關閉,可以直接在/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盡量回收記憶體。
c) 啟動mysql的時候,關閉numa特性:
numactl --interleave=all mysqld &
當然,最好的方式是在bios中關閉。
vm.swappiness是作業系統控制實體記憶體交換出去的政策。它允許的值是一個百分比的值,最小為0,最大運作100,該值預設為60。vm.swappiness設定為0表示盡量少swap,100表示盡量将inactive的記憶體頁交換出去。
具體的說:當記憶體基本用滿的時候,系統會根據這個參數來判斷是把記憶體中很少用到的inactive 記憶體交換出去,還是釋放資料的cache。cache中緩存着從磁盤讀出來的資料,根據程式的局部性原理,這些資料有可能在接下來又要被讀 取;inactive 記憶體顧名思義,就是那些被應用程式映射着,但是“長時間”不用的記憶體。
我們可以利用vmstat看到inactive的記憶體的數量:
#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
通過/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來使得該參數生效。
最後,我們看一下檔案系統的優化
用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選項。
在 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。
原文釋出時間:2014-07-28
本文來自雲栖合作夥伴“linux中國”