1. 程式人生 > >22.Mysql磁碟I/O

22.Mysql磁碟I/O

22.磁碟I/O問題
磁碟IO是資料庫效能瓶頸,一般優化是通過減少或延緩磁碟讀寫來減輕磁碟IO的壓力及其對效能的影響。
增強磁碟讀寫效能和吞吐量也是重要的優化手段。

22.1 使用磁碟陣列
RAID(Redundant Array of Inexpensive Disk)是指廉價磁碟冗餘陣列,即磁碟陣列。
RAID按照一定的策略將資料分佈到若干物理磁碟上,增加資料儲存的可靠性,提高資料的讀寫整體效能,實現了資料的並行讀寫。
22.1.1 常見RAID級別及其特性
根據資料分佈和冗餘方式,RAID分為不同的級別。
RAID 0:條帶化,按照一定的條帶大小將資料依次分佈到各個磁碟,沒有資料冗餘。優點:資料併發讀寫速度快,無額外磁碟開銷。缺點:資料無冗餘,可靠性差。
RAID 1:磁碟映象,兩個磁碟一組,所有資料都同時寫入兩個磁碟,可以從任一磁碟讀取。優點:資料完全冗餘,提高併發讀操作。缺點:磁碟有效容量只有總容量的一半。
RAID 10:RAID 0+RAID 1,先做磁碟映象再做條帶化,兼具RAID 1的可靠性和RAID 0的併發讀寫效能。優點:可靠性,併發讀寫效能優良。缺點:磁碟有效容量只有總容量的一半。
RAID 4:RAID 0+校驗糾錯,先做條帶化,額外增加一個磁碟做各個條帶的校驗糾錯資料。優點:一個磁碟損壞可以通過校驗糾錯資料計算出來,有一定的容錯能力,讀速度快。缺點:寫效能受影響。
RAID 5:改進RAID 4,將各個條帶的校驗糾錯資料也分別寫到各個磁碟中。優點:比RAID 4有更好的寫效能和資料保護能力。缺點:寫效能不及RAID 0、RAID 1、RAID 10,容錯能力不及RAID 1,出現壞盤時讀效能下降。
22.1.2 如何選擇RAID級別
資料庫 讀寫都很頻繁,可靠性要求高,選擇RAID 10;
資料倉庫 讀很頻繁,寫相對較少,可靠性有一定要求,選擇很RAID 5;
網站類 讀寫都很頻繁,可靠性要求不高,選擇RAID 0。

22.2 虛擬檔案卷或軟RAID
Linux的虛擬檔案卷或軟RIAD軟體支援模擬實現RAID,雖然效能上不如硬體RAID,但是比單個磁碟的效能和可靠性高。

22.3 使用Symbolic Links分佈I/O
針對MyIASM儲存引擎可以將表、索引的資料分不到不同的磁碟,其它儲存引擎不支援。
先在目標磁碟上建立目錄
#mkdir /otherdisk/databases/test
再建立從Mysql資料目錄到目標目錄的軟連線
#ln -s /otherdisk/databases/test /path/to/datadir
將MyIASM儲存引擎的資料檔案(.MYD)和索引檔案(.MYI)指向其它的物理磁碟,表定義檔案(.frm)不能指向其它磁碟。
>create table test(
id int primary key,
name varchar(20))
engine=myisam
data directory='/disk2/data'
index directory='/disk3/index';

22.4 禁止作業系統更新檔案的atime屬性
atime是一個檔案屬性,讀檔案時,作業系統會將當前時間更新到atime屬性上。
可以修改檔案系統配置檔案/etc/fstab來禁止更新檔案的atime屬性,以減輕磁碟IO負擔。
LABLE=/home /home ext3 noatime 1 2
重新mount檔案系統,即/home下的檔案不會修改檔案的atime屬性
#mount -oremount /home

22.5 用裸裝置(Raw Device)存放InnoDB的共享表空間
InnoDB使用快取機制儲存表和索引的資料,作業系統IO快取對其效能沒有幫助,可以使用Raw Device存放InnoDB的共享表空間。
修改my.cnf,在innodb_data_file_path引數中增加裸裝置檔名並指定neweaw屬性:
[mysqld]
innodb_data_file_path=/dev/hdd1:3Gnewraw;/dev/hdd2:2Gnewraw
啟動Mysql,使其完成初始化工作,然後關閉Mysql;
將innodb_data_file_path引數中的neweaw該成raw:
[mysqld]
innodb_data_file_path=/dev/hdd1:3Graw;/dev/hdd2:2Graw
重新啟動Mysql,即可開始使用。

22.6 調整I/O排程演算法
磁碟讀取資料的3個步驟:
將磁頭移動到磁碟表面的的正確位置,所花費的時間稱為尋道時間;
等待磁碟旋轉,需要的資料會移動到磁頭下面,所花費的時間稱為旋轉時間(與磁碟轉速有關);
繼續旋轉,所需要的資料都經過磁頭讀取,所花費的時間稱為傳輸時間。
尋道時間取值範圍[5ms-10ms],旋轉時間取值範圍[2ms-5ms],傳輸時間與資料量有關取值範圍[0ms-1ms]。
所以降低尋道次數,從而能夠優化磁碟IO。
作業系統將IO請求放入佇列,對請求進行合併和排序,即將相同或相鄰扇區的請求進行合併,並按請求資料所在磁軌由內向外的順序對請求排序,已達到一次尋道處理IO請求,減少尋道次數。
Linux的4種IO排程演算法:
NOOP演算法(No Operation):只對IO請求合併而不進行排序,使用先進先出FIFO佇列順序提交IO請求。
最後期限演算法(Deadline):IO請求在佇列內進行合併、排序,並維護帶有超時的寫請求對列和讀請求佇列。新請求被插入普通佇列和讀寫佇列,一般按照普通物件的順序處理請求,當讀寫佇列某個請求快要超時時將被優先處理。
預期演算法(Anticipatory):基於預測的IO演算法,在最後期限演算法(Deadline)的基礎上增加等待時間(6ms),等待時間內有相同扇區的新請求到達時優先處理新請求,否則按照普通佇列順序處理。
完全公平佇列(Complete Fair Queuing/CFQ):把IO請求按照程序分別放入每個程序的佇列中,以時間片演算法輪轉處理每個佇列的請求。
Mysql建議使用最後期限演算法(Deadline),如果是SSD建議使用NOOP演算法(No Operation)。
檢視當前系統支援的IO排程演算法:
#dmseg | grep -i scheduler
檢視當前裝置使用的IO排程演算法:
#more /sys/block/sda/queue/scheduler
修改當前塊裝置的IO排程演算法,修改後直接生效:
#echo "deadline" > /sys/block/sda/queue/scheduler
永久修改IO排程演算法,通過修改核心引導引數,增加elevator=排程程式名
#vi /boot/grub/menu.lst
kernel /boot/vmlinuz-2.6.18-308.e15 ro root=LABLE=/ elevator=deadline

22.7 RAID卡電池充放電問題
22.7.1 什麼是RAID卡電池充放電
RAID卡寫快取(Battery Backed Write Cache)有助於IO效能提升。
RAID卡寫快取有電池,用於斷電後將寫快取中的資料寫入磁碟,防止斷電導致的寫快取中的資料丟失。
RAID卡電池會定期充、放電,定期充、放電的操作稱為電池校準。
電池校準的3個階段:首先RAID控制器會將電池充滿,然後開始放電,再重新充滿。
檢視RAID卡電池狀態:
#MegaCli64 -AdpBbuCmd -GetBbuStatus -aAll

22.7.2 RAID卡快取策略
檢視RAID卡快取策略:
#MegaCli64 -LDInfo -Lall -aAll
寫快取策略,取值包括:WriteBack、WriteThrough。
WriteBack:將資料寫入RAID卡快取後直接返回,由RAID卡控制器負責將快取中的資料寫入磁碟。
WriteThrough:將資料直接寫入磁碟,不使用RAID卡快取。
是否開啟預讀,取值包括:ReadAheadNone、ReadAhead、ReadAdaptive。
ReadAheadNone:不開啟預讀
ReadAhead:開啟預讀,預先把後面順序的資料載入入快取,提升順序讀的效能,降低了隨機讀的效能。
ReadAdaptive:自適應預讀,在快取和IO空閒時進行順序預讀,否則不進行預讀。預設設定。
讀操作是否快取到RAID卡中,取值包括:Direct、Cached。
Direct:讀操作不快取到RAID卡中
Cached:讀操作快取到RAID卡中
電池問題時是否啟用Write Cache,取值包括:Write Cache Ok if Bad BBU、No Write Cache if Bad BBU。
No Write Cache if Bad BBU:電池問題時不啟用Write Cache,直接寫入磁碟。
Write Cache Ok if Bad BBU:電池問題時仍啟用Write Cache。
修改RAID卡快取策略:
#MegaCli64 -LDSetProp -WB -Lall -aAll -- 寫快取策略修改為WriteBack
#MegaCli64 -LDSetProp -WT -Lall -aAll -- 寫快取策略修改為WriteThrough
#MegaCli64 -LDSetProp -CachedBadBBU -Lall -aAll -- 電池問題時啟用Write Cache策略Write Cache Ok if Bad BBU
#MegaCli64 -LDSetProp -NoCachedBadBBU -Lall -aAll -- 電池問題時不啟用Write Cache策略No Write Cache if Bad BBU
再RAID卡電池校準期間或電池故障期間,預設RAID卡寫快取策略會從WriteBack變為WriteThrough,會造成系統寫入效能下降。
可以通過修改RAID卡快取策略調整,無需重啟。#MegaCli64 -LDSetProp -CachedBadBBU -Lall -aAll
等業務高峰期過後應即時修改為#MegaCli64 -LDSetProp -NoCachedBadBBU -Lall -aAll 避免斷電RAID卡寫快取資料丟失。

22.7.3 如何應對RAID卡電池充放電帶來的I/O效能波動
定期在業務量低的時候對RAID卡電池充放電,避免在高峰期發生寫快取策略切換(從WriteBack到WriteThrough)。
DELL伺服器RAID卡電池充放電週期為90天;IBM伺服器RAID卡電池充放電週期為30天。
從日誌檢視RAID卡電池下次充電時間:
#MegaCli64 -fwtermlog -dsply -a0 -nolog
從命令檢視RAID卡電池下次充電時間:
#MegaCli -AdpBbuCmd -GetBbuProperties -aall
手動觸發電池校準操作:
#MegaCli64 -AdpBbuCmd -BbuLearn -aALL
在有UPS電源的情況下可以強制設定寫快取策略為WriteBack,避免寫入效能波動。

22.8 NUMA架構優化
商用伺服器分類:SMP對稱多處理器結構(Symmetric Multi-Process)、NUMA非一致儲存訪問結構(Non-Uniform Memory Access)、MPP海量並行處理結構(Massive Parallel Processing)。
22.8.1 SMP架構
SMP架構一組CPU共享記憶體和匯流排,系統將任務佇列對稱地分佈在多個CPU上,各CPU平等的訪問記憶體、IO、外設,又稱為一致儲存訪問結構UMA。
SMP擴充套件方式有:增加記憶體、增加CPU、更換更高頻的CPU、擴充IO、增加磁碟。
SMP特徵是共享,缺點是通過同一套匯流排機制訪問,存在資源爭用而產生鎖等待。
22.8.2 NUMA架構
NUMA架構是將物理機分為多個節點,每個節點有一組CPU和記憶體,節點之間通過互聯模組進行連線和通訊。
每個CPU可以訪問物理機的整個記憶體,但是訪問本節點記憶體要快於訪問其它節點的記憶體。
顯示當前NUMA的節點情況:# numactl --hardware
空閒記憶體(單位MB):#:free -m
節點距離(Node Distances)是指CPU訪問本節點記憶體和其它節點記憶體的資源消耗度量。
預設CPU訪問本節點記憶體節點距離為10,訪問其它節點記憶體節點距離為21。
NUMA的記憶體分配策略有4種:
預設default:總是在本節點內分配;
繫結bind:在指定節點上分配;
交叉interleave:在所有節點或指定的多個節點上交叉分配;
優先preferred:優先在指定節點上分配,失敗則在其它節點上分配。
顯示當前系統的NUMA記憶體分配策略:# numactl --show
NUMA記憶體分配預設策略會導致各節點之間記憶體分配不均衡,某個節點產生Swap也不會從其它節點分配記憶體,這種現象稱為Swap Insanity。
Mysql是單程序多執行緒架構的資料庫,一個Mysql例項只能在一個NUMA節點上執行,使用本節點Swap也不會使用其它節點的記憶體的現象也會產生。
解決方法:
1.將NUMA的記憶體分配策略由default修改為interleave。
修改mysql啟動指令碼mysqld_safe,新增一行cmd="/usr/bin/numactl --interleave all $cmd",含義:在Mysql啟動時指定記憶體分配策略為interleave。
# vi $MYSQL_HOME/bin/mysqld_safe
cmd="/usr/bin/numactl --interleave all $cmd"
for i in "$ledir/$MYSQLD" "$defaults" "--basedir=$MY_BASEDIR_VERSION" \
"--datadir=$DATADIR" "--plugin-dir=$plugin-dir" "$USER_OPTION"
do
cmd="$cmd "`shell_quote_string "i"`
done
儲存後重啟Mysql。
2.在OS核心關閉NUMA特性
修改/etc/grub.conf檔案,在kernel那行追加numa=off
# vi /etc/grub.conf
...
kernel /boot/...quiet 追加numa=off
儲存後重啟伺服器,再次檢查numa節點:
# numactl --hardware 只剩一個節點了。
如果有多個Mysql例項,則可以指定到不同的節點上,採用繫結bind記憶體分配策略,Mysql緩衝區引數設定不能大於本節點的記憶體。
NUMA架構缺點在於跨節點的記憶體訪問存在延時,效能不是隨著CPU的數量線性增長的。
22.8.3 MPP架構
MPP架構由多個SMP伺服器通過一定的節點網際網路絡進行連線,每個節點只訪問本地資源,不訪問其它節點資源,這種Share Nothing架構理論上支援無限擴充套件。
節點之間的資訊互動通過節點網際網路絡實現,稱為DATA Redistribution。
MPP伺服器有機制來排程和平衡各個節點的負載和並行處理。

22.9 小結