MySQL磁盤IO設置問題
下面的部分內容來自《深入淺出MySQL》、老葉的視頻、網上其他人的blog。
這裏列出的是MySQL的一些非運行參數的優化部分,具體如下:
(對於使用雲主機的用戶,下文中的部分優化方法是無法奏效的)
0、使用SSD。資金不足的話,使用RAID設備 【建議使用RAID10,因為RAID5的性能並不太高】
可以SSD+SAS混合使用。SSD存放數據文件。mysql的日誌文件還是存在普通機械磁盤上,因為這些日誌本來就是順序IO的,存在SSD上浪費磁盤。
1、RAID卡設置
關閉讀cache:RAID卡上的cache容量有限,我們選擇direct方式讀取數據,從而忽略讀cache。
關閉預讀:RAID卡的預讀功能對於隨機IO幾乎沒有任何提升,所以將預讀功能關閉。
關閉磁盤cache:一般情況下,如果使用RAID,系統會默認關閉磁盤的cache,也可以用命令強制關閉。
以上設置都可以通過RAID卡的命令行來完成,比如LSI芯片的RAID卡使用megacli命令。
2、禁止操作系統更新文件的atime屬性
# vim /etc/fstab,將mysql數據文件存放的分區加上noatime掛載屬性即可,類似如下:
UUID=ccbb4c85-32ff-4b8d-ae58-f39569b67d96 /data ext4 defaults,noatime 1 2
# mount -o remount,noatime /data
# 查看設備UUID的命令: blkid /dev/sdb1
3、使用裸設備存放InnoDB的共享表空間 (目前很少這麽用了,直接用SSD)
vim my.cnf如下:
[mysqld]
innodb_data_home_dir=
innodb_data_file_path=/dev/hdd1:3Gnewraw;/dev/hdd2:2Gnewraw
然後啟動MySQL服務,讓其自動完成分區的初始化,然後關閉MySQL。此時還不能創建或修改InnoDB表。
將my.cnf的文件繼續修改下:
[mysqld]
innodb_data_home_dir=
innodb_data_file_path=/dev/hdd1:3Graw;/dev/hdd2:2Graw
然後重啟MySQL服務,即可使用。
4、關註RAID卡的BBWC (Battery Backed Write Cache 電池充放電)問題
RAID卡上自帶的電池會定期的充放電以進行電池校準。
每次充放電時間差不多3小時,期間RAID卡從數據安全角度考慮會自動禁用write back改為Write Through策略,這樣的話系統IO性能會出現較大的波動。這很大幾率會影響到MySQL的性能。
可以使用MegaCli64來查看和設置RAID卡緩存策略。如下:
# MegaCli64 -LDInfo -Lall -aALL 可以看到CurrentCache Policy 即當前的緩存策略。
我們可以臨時修改RAID卡策略,在電池充放電期間強制使用Write Cache OK if Bad BBU策略,等充放電完成後,再將其恢復成No Write Cache if Bad BBU,避免斷電可能導致的數據丟失。
另外,我們可以在業務低谷時候形象充放電操作,避免在業務高峰發生RAID卡充放電的執行。我們可以從BBU電池的日誌中找到下次電池reclean的時間:
# MegaCli64 -fwtermlog -dsply -a0 -nolog
或# MegaCli64 -AdpBbuCmd -GetBbuProperties -aall
也可以手動觸發電池的reclean操作:MegaCli64 -AdpBbuCmd -BbuLearn -aAll
5、調整磁盤IO調度算法
IO請求合並能減少磁盤尋道的次數。對於相鄰山區的訪問通過合並處理,對於非相鄰扇區的訪問則通過排序處理。
Linux下實現了4種IO調度算法。NOOP、最後期限算法Deadline、完全公平隊列算法CFQ、預期算法Anticipatory
2.6.17內核版本以後,系統默認是CFQ算法。
根據理論(這裏略過,需要了解的看《深入淺出MySQL》Page371),有如下結論:
1、在完全隨機的訪問環境下,CFQ和Deadline性能差異很小,但是在有大的連續IO出現的情況下,CFQ可能會造成小IO的響應延時增加,所以建議MySQL服務器設置為Deadline。
2、對於SSD設備,采用NOOP或Deadline通常可能獲取到比默認更好的性能。
修改磁盤IO調度算法的方法:
# dmesg|grep -i scheduler 查看到系統支持的IO調度算法【默認是noop anticipatory deadline [cfq]】
# more /sys/block/sda/queue/scheduler 查看當前使用的調度算法
# echo ‘deadline‘ > /sys/block/sda/queue/scheduler 修改後立即生效【臨時生效】
# vim /etc/grub.conf 在kernel行的末尾添加elevator=deadline 重啟即可永久生效
6、NUMA架構優化
常用服務器大體分為3類:
SMP 對稱多處理器結構
NUMA 非一致性內存訪問結構
MPP 海量並行處理結構
SMP主要的特征就是共享,系統中所有的資源資源都是共享的,導致SMP服務器的擴展能力非常有限。由於每個CPU都要通過相同的總線訪問相同的內存資源,如果兩個CPU同時請求訪問同一個內存資源(如同一段內存地址),就會產生資源爭用的問題。CPU越多這種情況出現的概率就越大。
NUMA把一臺計算機分成多個節點Nodes,每個節點內部擁有多個CPU,節點內部使用共有的內存控制器,節點之間是通過互聯模塊進行連接和信息交互。節點的所有內存對於本節點所有的CPU都是等同的,而對於其他節點中的所有CPU都是不同的。每個CPU可以訪問整個系統內存,但是訪問本地節點的內存較快,訪問非本地節點的內存較慢(要經過互聯模塊),即CPU訪問內存的速度和節點的距離有關,距離稱為Node Distance。
[[email protected] ~]# numactl --hardware
available: 2 nodes (0-1)
node 0 cpus: 0 1 2 3 4 5 12 13 14 15 16 17
node 0 size: 16349 MB
node 0 free: 2654 MB
node 1 cpus: 6 7 8 9 10 11 18 19 20 21 22 23
node 1 size: 16383 MB
node 1 free: 6079 MB
node distances:
node 0 1
0: 10 20
1: 20 10
[[email protected] ~]# free -m
total used free shared buffers cached
Mem: 32068 23335 8733 1 679 18982
-/+ buffers/cache: 3673 28395
Swap: 12137 88 12049
上圖可以看到有2個node,每個node的內存為16GB。上面的node distance中節點本地內存聲明距離為10,非本地節點內存聲明距離為20。
NUMA的內存分配策略有4種:
缺省 default 總是在本地節點分配(分配在當前進程運行的節點上)
綁定 bind 強制分配到指定節點上
交叉 interleave 在所有節點或指定節點上交叉分配內存
優先 preferred 在指定節點上分配,失敗則在其他節點上分配
[[email protected] ~]# numactl --show 顯示當前系統的NUMA策略
policy: default
preferred node: current
physcpubind: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
cpubind: 0 1
nodebind: 0 1
membind: 0 1
默認的default策略是優先在進程所在CPU的本地內存中分配,會導致CPU節點之間內存分配不均衡,當某個CPU節點內存不足時,會導致swap產生,而不是從遠程節點分配內存,這就是swap insanity現象。
MySQL是單進程多線程的架構。當NUMA采用默認default的分配策略時,MySQL進程會被並且僅被分配到NUMA的一個節點上去。假設MySQL配置的14G內存超過了這個節點的本地8G內存,這種情況下Linux寧願使用Swap也不會去瓜分其他節點的物理內存。這就導致一個問題:雖然free -m看上去還有內存可用,但是實際上MySQL進程已經開始使用到Swap了。
MySQL對NUMA的支持不太好,如果單機只運行的MySQL的話,建議關閉NUMA。方法如下:
# vim /etc/grub.conf 在kernel最後加上numa=off
保存後,重啟服務器即可。
關閉後,類似下面的樣子:
[[email protected] ~]# numactl --show
policy: default
preferred node: current
physcpubind: 0 1 2 3
cpubind: 0
nodebind: 0
membind: 0
或者通過numactl修改NUMA分配策略為interleave也行!!!
如果單機運行多個MySQL實例,我們可以將MySQL綁定在不同的CPU節點上,並且采用綁定的內存分配策略,強制在本節點內分配內存,這樣既可以充分利用硬件的NUMA特性,又避免了單實例MySQL對多核CPU利用率不高的問題。
7、文件系統設置
掛載時候可以不記錄時間:
defaults,noatime,nodiratime
補充:掛載時候使用 noatime,nodiratime 選項的問題
未指定"noatime,nodiratime"的情況下:
read文件的時候會導致atime更新,不會導致mtime和ctime更新
write文件只會導致mtime和ctime更新,不會導致atime更新。
說明:當以noatime選項加載(mount)文件系統時,對文件的讀取不會更新文件屬性中的atime信息。設置noatime的重要性是消除了文件系統對文件的寫操作,文件只是簡單地被系統讀取。
在平日裏經常有刪除文件的需求,大概如下:
刪除過去N天內都未訪問過的文件或者目錄(刪除N天前訪問過的文件)
# 註意這條命令很危險!
# find /home/fire/ -atime +N -exec rm -rf {} \;
假設 /home/fire 目錄是一周之前創建的,那麽對於這條命令有兩個執行結果:
# find /home/fire/ -atime +7 -exec rm -rf {} \;
指定"noatime":find的時候發現 /home/fire 是7天之前創建的,立馬就會刪除整個目錄。而且還會報錯"find: /home/fire: No such file or directory",原因就是第一個rm -rf /home/fire 之後 find失敗了。這種是很危險的!原因是會誤刪除文件。
未指定"noatime":那就得看情況,如果/home/fire過去7天沒有被訪問過,那麽就和情況一一樣,直接刪除。
如果過去7天內,該目錄有人訪問過,atime肯定是7天之內,那麽就會遍歷下面的目錄,依次按照之前邏輯。但是遍歷過程會更改目錄的atime。
看了上面的例子會發現find去刪除目錄的時候變得好復雜,而且一定要小心。所以find刪除更適用於刪除文件,不要刪除目錄。
啟用noatime的時候,刪除N天內未被訪問過的文件的方法:
# find /home/fire/ -atime +N -type f -exec rm -f {} \;
本文出自 “一只菜雞的筆記” 博客,請務必保留此出處http://lee90.blog.51cto.com/10414478/1971324
MySQL磁盤IO設置問題