Chapter 7 故障報告書 — 數據庫 CPU 100%

我接手時候生產環境只有一個 MySQL 實例,負責全體讀寫請求。那時候 AWS 還沒推出數據庫叢集 Database cluster,只有 readonly replicate 方案。所以搭配了 replicate 技術,開設了第二顆只讀實例出來,開始把很多請求壓力大,轉到只讀實例上,把 CPU 用量需求分散掉。
數據庫 CPU 資源不夠用時候,所有平台是會停擺的,不能查、不能寫,產品是幾乎不能用的。所以這個報警到群裡,是非常恐怖非常緊張需要第一時間處理,哪怕你剛走出門用餐。在這份工作日子裡,可以讓技術小夥伴栽培成數據庫專家。技術團隊先來看哪些情況會發生數據庫 CPU 居高不下,再來定位問題開始改善,過程操作要監控數據庫本身實例健康狀況,然後作為之後長久發展計畫。
定位問題
CPU 使用跟查詢有直接關係,用戶端安卓 App 請求是最大宗,所有的查詢都是以萬級使用量在查,所以這影響了 CPU 資源大盤走勢,每天走勢圖很明顯,夜裡就是控制在 30~40%,當太陽升起,CPU 也開始上升到 60%~70%,然後當深夜裡又下降回來。一個 SQL 查詢花費時間也是會帶動 CPU 用量,平台數據部分非常需要查大量數據分析,所以 SQL 寫的暴力一點,查詢不出來,CPU 是會往 90~100% 衝的。
SQL 慢查詢是影響 CPU 資源使用,所以技術夥伴們三天兩頭會掉出數據庫所有慢查詢,分析哪些是誰寫的,哪個功能使用,為什麼要這樣查。如果 SQL 查詢太長太特殊,就會跟數據部門問,是不是他們查的。後來技術夥伴們切了主寫、只讀兩個實例後,就不太需要問數據部門了,數據部門都切去使用只讀實例就可以分析。慢查詢原因是要查的量大,或者取回的數據太多。
改善方案
要解決慢查詢都是要從索引去改善。如果在 where 條件一個索引都沒加沒有命中,會全表查詢,平台的數據表數據平均百萬級、千萬級都有,所以全表查資源肯定會不夠。技術夥伴們會用 MySQL Explain 先看有沒有命中,如果沒有命中,就看是不是少建立索引,如果少建立索引,就要安排離峰時段來建立索引。
建立索引還用到了復合索引,這樣他一個 where 裡面有多條件,不會只選一種來用,而是先過濾出一種,再深入第二層過濾,會快非常多。因為數據表已經是百萬級、千萬級才發現沒建立索引,要建立時候是個頭痛問題。技術夥伴們經驗抓過緊繃數值,如果數據表量到 300 萬,建立索引會需要大約 9 分鐘,建立過程整個數據庫是非常緊張,執行時候,都要打開 Show processlist 看有沒有影響到其他查詢語句。
如果超過 300 萬的數據表,只好用另外一種高級高階做法。先複製一個新的表出來,把索引先建立好,然後開始同步數據,把原來百萬級、千萬級數據透過 select insert 開始同步開始大批量寫入。當數據同步完成後,透過 rename table,將 A 表命名成 C,將 B 表命名成 A,再把 C 表命名為 B,一種拿杯子換水概念。然後再把剛剛執行過程數據再小部分寫回來。
長久發展計畫
技術小夥伴都非常熟悉數據庫所有知識,從建表建立外鍵、建立索引,到查是否產生慢查詢,在數據量百萬級以下就要調整到最佳狀態,這樣可以避免數據量百萬級、千萬級還要做危險動作,耗費時間壓力又大。數據部門在試算風險係數,是拿這用戶過去所有數據在分析的,數據庫數據只會增加,沒有做過搬家冷備份,所以數據庫只能越用越小心,深怕他哪天會撐不住。
我將這段印尼市場 FinTech 互聯網金融創業故事寫成了一本電子書小說,書名叫做乘風破浪現金貸。整書已經全部完成第一版,總計有 15000 字。可以在日傑資訊官網商城購買完整版 https://www.soleil.tw/#store ,你招待一杯咖啡,我把這段永生難忘故事慢慢講給你聽。
