Linux

部分 RAID 陣列的間歇性 I/O 延遲導致 MySQL 性能不佳

  • June 12, 2017

我正在管理執行 MySQL 數據庫以及其他一些軟體的裸機伺服器。我們看到一些 MySQL 查詢存在性能問題,但這些問題是間歇性發生的,並且幾乎完全影響 UPDATE 查詢。

例如,我有一個大約每 15 秒執行一次的特定查詢。大多數情況下它會在幾毫秒內完成,但有時查詢分析會顯示:

Status                          Duration
starting                        0.000026
checking permissions            0.000003
Opening tables                  0.000011
System lock                     0.000002
init                            0.000007
update                          0.000052
Waiting for query cache lock    0.000001
update                          0.000002
end                             0.000001
query end                       15.198987
closing tables                  0.000023
freeing items                   0.000026
logging slow query              0.000014
logging slow query              0.000001
cleaning up                     0.000002

我嘗試了this question中的建議,但沒有效果。然後我開始查看較低級別的項目,因為我注意到其他一些軟體也表現出間歇性緩慢響應。

這是性能良好時的最高輸出:

top - 12:09:48 up 138 days, 21:57,  2 users,  load average: 2.35, 1.73, 1.55
Tasks: 392 total,   2 running, 388 sleeping,   2 stopped,   0 zombie
%Cpu0  : 16.4 us,  1.3 sy,  0.0 ni, 80.3 id,  1.0 wa,  0.0 hi,  1.0 si,  0.0 st
%Cpu1  :  9.3 us,  0.7 sy,  0.0 ni, 89.1 id,  0.7 wa,  0.0 hi,  0.3 si,  0.0 st
%Cpu2  :  4.0 us,  0.7 sy,  0.0 ni, 95.0 id,  0.3 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu3  :  3.0 us,  0.7 sy,  0.0 ni, 96.3 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu4  : 10.0 us,  0.7 sy,  0.0 ni, 89.3 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu5  : 14.9 us,  0.7 sy,  0.0 ni, 84.4 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu6  :  2.6 us,  0.3 sy,  0.0 ni, 96.4 id,  0.7 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu7  :  1.3 us,  0.0 sy,  0.0 ni, 98.0 id,  0.7 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem:  32836768 total, 24516984 used,  8319784 free,   143868 buffers
KiB Swap:        0 total,        0 used,        0 free. 15166836 cached Mem

 PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
26264 root      20   0 1255040  81148  17792 S  19.3  0.2 367:38.32 node
1450 root      20   0 1249548 106060  17760 S   7.6  0.3   2612:39 node
30815 root      20   0 1245184  71652  17780 S   5.6  0.2 898:00.21 node
20700 root      20   0 1238644  63004  16812 S   2.3  0.2 635:20.34 node
 281 root      20   0  193348 101184  97840 S   2.0  0.3   2832:15 systemd-journal
2974 root      20   0   48404  21688   3812 S   1.3  0.1   1329:51 openvpn
26283 postgres  20   0  235384  45408  42648 S   1.3  0.1  10:17.88 postgres
26284 postgres  20   0  235380  44780  42008 S   1.3  0.1  10:14.81 postgres
25764 root      20   0 1232976  58792  17716 S   1.0  0.2  42:51.01 node
26279 postgres  20   0  235356  45772  43028 S   1.0  0.1  10:13.60 postgres
12793 root      20   0   23956   3300   2488 R   0.7  0.0   0:00.11 top
26280 postgres  20   0  235384  44764  41992 S   0.7  0.1  10:16.64 postgres
27135 postgres  20   0  235380  44932  42156 S   0.7  0.1  10:15.24 postgres
27136 postgres  20   0  235360  44288  41532 S   0.7  0.1  10:15.45 postgres

當它不好時:

top - 12:13:19 up 138 days, 22:00,  2 users,  load average: 3.34, 2.45, 1.88
Tasks: 393 total,   2 running, 389 sleeping,   2 stopped,   0 zombie
%Cpu0  : 11.1 us,  0.0 sy,  0.0 ni,  0.0 id, 87.8 wa,  0.0 hi,  1.0 si,  0.0 st
%Cpu1  :  1.3 us,  0.0 sy,  0.0 ni, 75.5 id, 22.8 wa,  0.0 hi,  0.3 si,  0.0 st
%Cpu2  :  5.7 us,  0.3 sy,  0.0 ni,  8.4 id, 85.6 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu3  : 11.0 us,  0.3 sy,  0.0 ni, 74.3 id, 14.3 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu4  :  0.7 us,  0.0 sy,  0.0 ni, 87.3 id, 12.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu5  :  1.3 us,  0.0 sy,  0.0 ni, 98.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu6  :  1.0 us,  0.0 sy,  0.0 ni, 99.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu7  :  3.0 us,  0.3 sy,  0.0 ni, 93.3 id,  3.4 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem:  32836768 total, 24870588 used,  7966180 free,   143868 buffers
KiB Swap:        0 total,        0 used,        0 free. 15073140 cached Mem

 PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
26264 root      20   0 1252992 109712  17792 S  10.0  0.3 368:16.02 node
1450 root      20   0 1255692 112632  17760 S   4.3  0.3   2612:57 node
30815 root      20   0 1240064  81032  17780 S   4.0  0.2 898:13.71 node
20700 root      20   0 1243764  74472  16812 S   2.3  0.2 635:24.22 node
 281 root      20   0   58644  22468  19124 S   1.0  0.1   2832:18 systemd-journal
25764 root      20   0 1240144  64560  17716 S   1.0  0.2  42:53.01 node
2974 root      20   0   48404  21688   3812 S   0.7  0.1   1329:53 openvpn
   7 root      20   0       0      0      0 S   0.3  0.0 728:52.82 rcu_sched
 770 postgres  20   0  235648  45920  42780 S   0.3  0.1   8:11.67 postgres
5476 root      20   0       0      0      0 S   0.3  0.0   0:00.15 kworker/u16:1
12329 root      20   0       0      0      0 D   0.3  0.0   0:00.18 kworker/2:1
12778 root      20   0       0      0      0 R   0.3  0.0   0:00.25 kworker/2:2
26278 postgres  20   0  232340  17764  15544 S   0.3  0.1   5:38.38 postgres
28478 mysql     20   0 7210212 3.677g   8560 S   0.3 11.7   1849:14 mysqld
30829 postgres  20   0  232340  17484  15272 S   0.3  0.1  14:01.09 postgres
   1 root      20   0   28968   5188   2864 S   0.0  0.0   5:44.60 systemd
   2 root      20   0       0      0      0 S   0.0  0.0   0:12.38 kthreadd
   3 root      20   0       0      0      0 S   0.0  0.0  75:39.66 ksoftirqd/0
   5 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/0:0H
   8 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcu_bh

遵循一些有關在 Linux 中解決高 I/O 等待問題的建議,我執行了iostat -xm 5.

這是一個正常的輸出:

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
          6.05    0.00    0.63    0.80    0.00   92.52

Device:         rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sda               0.00     2.60    0.00   58.40     0.00     0.64    22.58     0.02    0.32    0.00    0.32   0.29   1.68
sdb               0.00     2.80    0.00   58.20     0.00     0.64    22.66     0.12    2.10    0.00    2.10   1.70   9.92
md0               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
md1               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
md2               0.00     0.00    0.00   24.00     0.00     0.10     8.53     0.00    0.00    0.00    0.00   0.00   0.00
md3               0.00     0.00    0.00   27.80     0.00     0.53    39.19     0.00    0.00    0.00    0.00   0.00   0.00
dm-0              0.00     0.00    0.00   24.20     0.00     0.53    45.02     0.22    9.06    0.00    9.06   2.64   6.40

和緩慢的輸出:

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
          3.90    0.00    0.28   51.05    0.00   44.77

Device:         rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sda               0.00     7.20    0.00   42.20     0.00    15.24   739.82     0.35    8.27    0.00    8.27   0.74   3.12
sdb               0.00     7.40    0.00   62.00     0.00    24.69   815.55   110.16 2142.10    0.00 2142.10  16.13 100.00
md0               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
md1               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
md2               0.00     0.00    0.00    0.40     0.00     0.00    24.00     0.00    0.00    0.00    0.00   0.00   0.00
md3               0.00     0.00    0.00    0.20     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
dm-0              0.00     0.00    0.00    0.20     0.00     0.00     8.00   219.50 3880180.00    0.00 3880180.00 5000.00 100.00

sda 和 sdb 是三星 SSD 850 EVO 1TB 驅動器。每個都有一個相同的分區表,在 RAID1 上創建四個 md 設備:

Personalities : [raid1] 
md3 : active raid1 sda4[0] sdb4[1]
     940987072 blocks super 1.2 [2/2] [UU]
     bitmap: 2/8 pages [8KB], 65536KB chunk

md2 : active raid1 sda3[0] sdb3[1]
     19514368 blocks super 1.2 [2/2] [UU]

md1 : active raid1 sda2[0] sdb2[1]
     15617024 blocks super 1.2 [2/2] [UU]

md0 : active raid1 sda1[0] sdb1[1]
     487104 blocks super 1.2 [2/2] [UU]

md0 是 /boot,輸入 xfs。md1 用於交換,但目前未使用。md2 是 /,輸入 xfs。最後,md3 是儲存數據的加密卷 (dm-0) 的備份設備:

LUKS header information for /dev/md3

Version:        1
Cipher name:    aes
Cipher mode:    xts-plain64
Hash spec:      sha1
Payload offset: 4096

特別困擾我的是 sdb 上的 I/O 負載似乎比 sda 上高得多。由於兩個磁碟都只為 RAID1 陣列提供成員分區,這似乎不對。

我檢查了 sdb 的 SMART 數據,並執行了短期和長期自檢,沒有檢測到問題:

SMART Error Log Version: 1
No Errors Logged

SMART Self-test log structure revision number 1
Num  Test_Description    Status                  Remaining  LifeTime(hours)  LBA_of_first_error
# 1  Extended offline    Completed without error       00%      8719         -
# 2  Short offline       Completed without error       00%      8711         -

除了每 30 分鐘 smartd 記錄溫度變化外,系統日誌沒有顯示 sdb 的條目。

核心版本:

Linux no 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt25-2+deb8u3 (2016-07-02) x86_64 GNU/Linux

我錯過了什麼?

根據您的iostat輸出,sdb似乎有一個很長的 I/O 隊列,相應的等待時間也很長。

為什麼這只發生在sdb,而不是兩個磁碟上?這是一種可能的解釋:當您第一次配置 RAID 設備時,所有 sda內容(甚至是無效/垃圾內容)都被複製到sdb. 這會自動將所有塊標記為已使用,sdb從而為快閃記憶體塊/頁面回收留下非常少的空間(僅少量過度配置)。這會對消費級磁碟造成嚴重破壞,控制器實際上會暫停所有 I/O 操作以垃圾收集一些快閃記憶體塊。

加密分區加劇了這種情況,對於磁碟控制器來說,它基本上看起來像是一個大的二進制部落格。

現在做什麼?如果您的 LUKS 安裝(以及它下面的所有 I/O 堆棧)支持 ATA TRIM 傳遞,您可以簡單地發出fstrim -v <mntpoint>命令將所有可用空間標記為未使用。如果它有效,我建議您安排一個夜間 cronjob 在低負載時間自動執行它。在這裡查看更多資訊。

如果您的設置不支持 TRIM passdown,那麼您就不走運了:在這種情況下,您必須安全擦除磁碟並重新分區,至少留出 25% 的空間未分配。在某些情況下甚至需要使用hdparm設置適當大小Host Protected Area來手動設置更多的過度配置;但是,三星 850 EVO 不需要這樣做。

引用自:https://serverfault.com/questions/854905