1. 程式人生 > >MySQL磁盤IO設置問題

MySQL磁盤IO設置問題

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設置問題