AWS快速開戶 AWS EBS 雲碟 IOPS 達到上限導致資料庫卡死?burst 點數與預置 IOPS 排查
先看結論:資料庫不是突然壞掉,而是卡在 I/O 等待
很多人遇到資料庫「整個卡死」時,第一反應是 SQL 壞了、鎖太多、主從有問題,甚至懷疑應用程式寫錯。實際上,真正的兇手常常是 AWS EBS 雲碟已經到達 IOPS 上限,或者 burst 點數用完,導致磁碟延遲一路飆高,請求在排隊,資料庫看起來就像當機。
這種故障最麻煩的地方,不是它難解,而是它很容易被誤判。CPU 可能不高,記憶體也沒爆,連網路都正常,但所有查詢就是慢得離譜,連登入都要等半天。因為瓶頸不在算力,而在資料落盤與回寫。只要寫入要等磁碟,交易就會卡住;交易一卡住,連帶把連線池、背景工作、佇列任務一起拖下水。
要把這類問題查清楚,關鍵不是先猜,而是先分層判斷:到底是 EBS 本身的限制、執行個體到 EBS 的頻寬限制,還是資料庫內部的 flush、checkpoint、鎖等待造成的連鎖反應。順序抓對了,問題通常不難收斂。
一、EBS 的 IOPS 到底卡在哪裡
IOPS、吞吐量、延遲是三件不同的事
很多故障報告只寫一句「磁碟滿了」,但真正要看的不是容量,而是 IOPS、吞吐量和延遲。IOPS 是每秒能處理多少次 I/O 請求;吞吐量是每秒能搬多少資料;延遲則是單次請求從送出到完成要等多久。資料庫最怕的通常不是大容量傳輸,而是大量隨機讀寫,因為每次都要跟磁碟對話,延遲一高,整體就會被拖慢。
舉例來說,批次匯入、索引重建、checkpoint、WAL/redo log flush、備份還原,都可能把 I/O 推到高峰。這時候如果磁碟型號本來就偏保守,或者規格設得太低,系統平常看起來沒事,一到尖峰就開始排隊。排隊一長,應用層看到的就是 timeout、重試、交易失敗,最後像是資料庫整台死掉。
gp2 的 burst 點數:平時夠用,尖峰就露餡
gp2 是最常見的坑。它的特色是依照容量提供基礎 IOPS,平時看起來很划算,遇到短時間尖峰還能靠 burst 點數撐一下。問題在於,很多人以為「能 burst」就代表永遠夠用,事實不是。burst 點數是會耗盡的,一旦耗盡,性能就回到基礎值。
這也是為什麼有些系統上線初期很順,跑了十幾分鐘、半小時、甚至幾個小時後突然開始卡。因為前面已經把信用額度花掉了。若你的工作負載是持續性的寫入,像訂單系統、事件收集、日誌寫入、資料同步,burst 很快就不夠用。等到 burst 點數掉到接近零,延遲會瞬間變得很難看,資料庫就像被按了暫停鍵。
gp2 還有一個迷思:只要把容量加大,IOPS 就會跟著變好。這句話只對一半。容量變大確實可能提高基礎 IOPS,但成本也一起上升,而且不是所有場景都值得用「堆容量」來換性能。更麻煩的是,很多人只看月費,沒看尖峰時段的真實需求,結果花了錢,問題卻沒解掉。
預置 IOPS:把上限買下來,不代表可以亂用
如果你的資料庫負載穩定,而且 I/O 壓力本來就不低,預置 IOPS 類型通常比 gp2 更合適。像 gp3、io1、io2 都能把 IOPS 和容量分開管理,讓性能更可預測。gp3 預設就有一定 IOPS 和吞吐量,對大多數資料庫來說,比 gp2 更容易控管;io1、io2 則更適合要求高穩定、低延遲的核心系統。
但「預置」不等於「無上限」。如果你把 IOPS 設太低,一樣會卡;如果執行個體本身的 EBS 頻寬上限先到了,就算雲碟規格很高,也一樣跑不快。也就是說,瓶頸不只在磁碟,還可能在執行個體與 EBS 之間的傳輸能力。這一點常被忽略,因為大家只看磁碟類型,忘了整條路徑都要一起檢查。
二、資料庫真的卡住時,會看到什麼現象
真正的 I/O 瓶頸,通常不是單一 SQL 慢,而是整個系統一起慢。常見症狀包括:查詢開始超時、連線池耗盡、後台任務排隊、批次作業卡在中途、頁面回應時間突然拉長。更讓人困惑的是,CPU 可能看起來不高,甚至有明顯空閒,但使用者體感卻像機器掛了。
- 交易提交很慢,明明 SQL 很簡單,卻卡在 commit。
- 大量 session 在等 disk I/O、fsync、flush 或 checkpoint。
- iowait 偏高,CPU 利用率卻不一定高。
- CloudWatch 的佇列深度上升,磁碟延遲一路拉長。
- 寫入比讀取更容易先出問題,尤其是高頻小寫入。
這類問題還有一個特徵:不是所有查詢都慢,而是整個系統的尾延遲變差。也就是說,前 90% 的請求也許還能接受,但最後那 10% 會慢到離譜。對使用者來說,體感就是「偶爾卡一下」,但對資料庫來說,那些卡住的請求已經足以把一連串交易拖垮。
三、排查順序:先證明是磁碟,再談資料庫
先看 CloudWatch,別急著進資料庫改參數
第一步先看雲端監控。若是 gp2,重點是 BurstBalance、VolumeQueueLength、ReadOps、WriteOps、ReadLatency、WriteLatency。BurstBalance 持續往下掉,最後接近零,幾乎就能說明問題方向。若佇列深度持續升高,延遲也同步上升,而讀寫操作數卻上不去,通常就是磁碟已經飽和。
如果是 gp3、io1 或 io2,就不要再盯 BurstBalance,因為這類磁碟不是靠 burst 來撐。你應該看的是實際 IOPS 是否貼近設定值、吞吐量是否碰到上限、延遲是否在高峰時段明顯抖動。若你的設定本來就偏低,CloudWatch 會很誠實地告訴你:不是資料庫神奇變慢,而是規格不夠。
還有一種情況是,磁碟本身沒爆,但執行個體端的 EBS bandwidth 先滿了。這時你會看到吞吐量上不去,延遲卻已經開始變差。這也是為什麼單看磁碟類型不夠,還要看執行個體規格能不能承受當前負載。
再看作業系統,確認是不是 I/O wait
進到主機後,可以用 iostat -x 1 看磁碟的平均等待時間、利用率與隊列深度;再搭配 vmstat 觀察 wa,也就是 iowait。如果磁碟 util 長時間接近 100%,await 越來越高,wa 也跟著升,那就不是猜測,而是實際上已經在等磁碟。
這時候 top 可能會讓人誤會,因為 CPU 並沒有滿,甚至看起來很閒。可是一台機器是不是忙,不只看 CPU。當程序都在等 I/O,CPU 本來就會空下來。真正的線索不是 CPU 有多高,而是系統是不是把時間花在等待資料落盤。
如果是多個卷一起用,也要確認是不是某個附加卷先爆了。像資料檔、日誌檔、臨時檔、備份檔如果混在同一顆磁碟上,很容易一個背景任務把全部流量吃掉。看似是資料庫卡住,其實是某個批次作業把整顆碟壓滿了。
最後回到資料庫,看誰在等落盤
到了資料庫層,就要找出是否存在大量 fsync、flush、checkpoint 或 redo/WAL 寫入等待。MySQL 可以看 processlist、InnoDB 狀態、慢查詢紀錄;PostgreSQL 則可以看 pg_stat_activity、checkpoint 行為與 WAL 寫入情況。若大量連線都卡在 commit 或 flush,不必先懷疑 SQL;先懷疑磁碟。
如果只有少數查詢慢,可能是索引、鎖或執行計畫問題;但如果是整片一起慢,多半是共享資源出問題。這個差別非常重要。很多團隊一看到慢查詢就開始改 SQL,改到最後問題沒解,反而把原本穩定的執行計畫弄壞。查障礙要從症狀範圍下手,範圍越大,越像底層資源瓶頸。
四、不同磁碟類型的典型坑
gp2:最容易出現「前面正常,過一陣子突然全慢」
gp2 的麻煩在於,它很適合低成本、輕負載,但一旦工作負載變成持續高 IOPS,就會開始暴露問題。你可能看到前幾十分鐘一切正常,之後延遲突然往上跳,查詢開始堆積,這常常不是偶發,而是 burst 點數已經用完。
舉個直白的例子,若一個 100GiB 的 gp2 卷基礎 IOPS 約為 300,而你的系統長時間需要 3000 IOPS,那超出的部分都在消耗信用額度。這種情況下,點數很可能在短時間內被耗盡,然後性能從「看起來夠用」瞬間掉回「完全不夠用」。這也是為什麼很多問題不是一開始就爆,而是跑一段時間後才爆。
AWS快速開戶 gp3:容量和性能分離,別只改容量
gp3 的優點是把容量和性能拆開,使用者不用為了 IOPS 被迫加大容量,這對多數資料庫來說很實際。但它也有一個常見誤區:很多人把 gp2 直接換成 gp3,卻只改了磁碟類型,沒注意 IOPS 和吞吐量是否符合實際負載。結果表面上升級了,實際上性能設定還是偏低。
對穩定的 OLTP 系統來說,gp3 往往已經足夠;但如果有明顯尖峰、批次寫入、同步複寫壓力,或者需要很低的尾延遲,就要把 IOPS 和吞吐量一起評估。只改容量不改性能設定,通常只是把舊問題換個地方藏起來。
io1、io2:高穩定,不代表沒有瓶頸
io1、io2 的價值在於可預測性。對交易核心、重要寫入、延遲敏感服務來說,穩定往往比便宜更重要。不過即使你用了高階磁碟,也不要以為就萬事大吉。執行個體本身的 EBS 頻寬可能有限,多顆卷做 RAID0 雖能拉高吞吐,但如果管理不當,也會把故障面擴大。
另外,資料庫本身的設定也會影響效果。若 buffer pool 太小,讀寫都會被迫頻繁打到磁碟;若 checkpoint 太急,寫入就會出現尖峰;若背景刷盤策略不合理,磁碟即使性能夠,也可能被不健康的寫入節奏拖累。硬體升級是基礎,但不是唯一答案。
AWS快速開戶 五、真正有效的修法,不是只會升級規格
先抓峰值,再看持續量
很多容量規劃失敗,不是因為不會算,而是只看平均值。平均 IOPS 很低,不代表峰值不高;白天很正常,不代表晚上批次不會爆。你應該看的是高峰時段的 95 百分位,甚至更保守一點,去看最壞情況會不會讓延遲失控。
如果你的業務是固定尖峰,例如整點批次、結帳時段、活動開始瞬間,那就不能用平日均值來估算。真正要問的是:這顆碟在連續高壓下能撐多久?如果只能撐幾分鐘,卻要跑半小時的批次,那遲早會出事。
把資料檔和日誌檔拆開
對大多數資料庫來說,日誌檔比資料檔更敏感,因為它關係到 commit 是否能完成。若資料檔、redo log、臨時檔都在同一顆卷上,任何一種 I/O 高峰都可能互相干擾。把日誌和資料拆開,常常比盲目加大磁碟更有效。
如果系統還有備份、ETL、匯入匯出、批次報表,最好也不要跟線上交易搶同一份 I/O。線上交易需要的是穩定延遲,離線工作則可以稍微慢一點。把兩者混在一起,最後通常是誰都不滿意。
調整資料庫本身的 I/O 行為
除了換磁碟,資料庫本身也要調。MySQL 可以檢查 innodb_buffer_pool_size、innodb_io_capacity 之類的設定,讓刷盤節奏更合理;PostgreSQL 則要留意 shared_buffers、checkpoint_timeout、max_wal_size 與 autovacuum 行為。這些參數的目的,不是硬把磁碟壓榨到極限,而是避免形成明顯的寫入風暴。
AWS快速開戶 不過要記住,參數調整是減壓,不是治本。若磁碟規格根本不夠,單靠調參只能延後爆炸時間。真正健康的做法,是把資料庫行為和磁碟能力配平,讓系統在正常壓力下維持穩定,而不是靠運氣撐過每天的高峰。
監控要提早報警,不要等使用者先罵
最實用的做法,是把 BurstBalance、VolumeQueueLength、ReadLatency、WriteLatency、iowait 都納進告警。當 BurstBalance 低到某個門檻,或佇列深度開始持續上升時,就應該先收到通知,而不是等資料庫已經卡死才回頭看圖表。等到所有人都感受到慢,通常已經錯過最佳處理時機。
容量規劃也是同一件事。只看當前規格,永遠追不上成長速度;只有把趨勢拉出來,才知道什麼時候該升級、該拆卷、該搬到 gp3 或 io2。監控不是為了漂亮報表,而是為了讓你在事故發生前做決定。
六、實戰判斷清單
- 如果 CPU 不高、iowait 卻高,先查磁碟,不要先改 SQL。
- AWS快速開戶 如果 gp2 的 BurstBalance 一路下降,幾乎可以直接鎖定問題。
- 如果換大實例後沒改善,回頭看 EBS 頻寬上限是否已經碰到。
- 如果只改了 gp3 容量,卻沒調 IOPS 和吞吐量,等於沒升級。
- 如果整站一起慢,不像單一查詢問題,通常是共用 I/O 資源出問題。
- 如果慢的是 commit、fsync、checkpoint,優先懷疑落盤而不是計畫錯誤。
結語:資料庫卡死,很多時候只是磁碟在求救
AWS EBS IOPS 達到上限時,系統的表現很像資料庫當機,但本質多半是資源排隊。只要你把問題拆成三層來看:雲碟是否飽和、執行個體是否受限、資料庫是否在不合理地刷盤,通常就能很快找到根因。gp2 的 burst 點數、gp3 的預置設定、io1/io2 的穩定度差異,都是排查時一定要懂的基本功。
真正成熟的做法,不是等出事再補救,而是先把工作負載、磁碟能力和監控告警對齊。當你知道系統在什麼情況下會接近上限,就能在使用者感受到卡頓之前,把問題壓下去。資料庫不怕忙,怕的是忙得沒有節制,最後把磁碟壓成瓶頸。

