1. 程式人生 > >排查Mysql突然變慢的一次過程

排查Mysql突然變慢的一次過程

# 排查Mysql突然變慢的一次過程 ![mysql.jpg](https://i.loli.net/2020/08/06/g6Cu4LD5trJnc9k.jpg) 本文源地址:[排查Mysql突然變慢的一次過程](https://yanzhenyidai.com/#/db/mysql-cpu-hight) > 上週客戶說系統突然變得很慢,而且時不時的蹦出一個 `404` 和 `500`,弄得真的是很沒面子,而恰巧出問題的時候正在深圳出差,所以一直沒有時間 看問題,一直到今天,才算是把問題原因找到。 --- ## 定位問題 剛開始得到是系統慢的反饋,沒有將問題點定位到資料庫上,查了半天服務是否正常(因為之前有一次Dubbo記憶體洩漏)。 在將應用服務日誌查看了一遍後,沒有發現任何異常,只是打了幾個警告的日誌。 於是又查看了業務執行時的日誌,看到日誌都提示了一個 `Lock wait timeout exceeded; try restarting transaction` 的異常。 這時還是沒有將重心放到資料庫上,認為是程式碼的原因,導致事務一直沒有提交。 重新將程式碼審閱了一遍,覺得應該不是程式碼邏輯的問題,而這個時候, `Lock wait timeout exceeded; try restarting transaction` 這個異常的日誌越來越多。 認為是資料庫層面出了問題,開始排查資料庫。 --- ## 尋找原因 由於我們的資料庫不是用的 `雲RDS版本`,是在一臺8核32G的AWS上的安裝版本。 使用 `top` 命令,檢視到 Mysql 佔用的 CPU 使用率高達 90% 左右。 心裡一慌,感覺不妙,這樣子高負載的CPU使用率,搞不好伺服器都要宕掉。 於是拿出了僅有的一點Mysql基本知識,基本上這次只使用到了下面幾個語句: - 檢視當前Mysql所有的程序 `show processlist;` - 檢視Mysql的最大快取 `show global variables like "global max_allowed_packet"` - 檢視當前正在進行的事務 `select * from information_schema.INNODB_TRX` - 檢視當前Mysql的連線數 `show status like 'thread%'` --- ## 解決 按照上面的幾個語句,一步一步跟蹤定位下來。 > `show processlist;` 下來,我們就可以查看出當前所有的程序,並且得到最耗時的程序。 在當前資料庫中,看到處於 `Sleep` 狀態的SQL非常多,而這也是佔用CPU過高的重大原因,休眠執行緒太多,於是配置了一個 `wait_time_out` 為 600 秒的一個解決方案。 為什麼配置600秒,因為我們應用超時時間配置的最大時間就是 600秒,10分鐘,這裡的配置需要根據業務來具體配置。 > `select * from information_schema.INNODB_TRX` 執行這個語句,看到Mysql中大部分處於 `Lock` 的SQL是一條 update 的SQL,而且還有一個單條件的SQL,查詢居然耗時4分鐘,很是驚訝。 於是查看了這張表。 剛一開啟結構,差點沒忍住口吐芬芳,居然一個索引都沒有,資料量超過300W,沒有索引查詢基本上都要4分鐘往上走。 於是準備加上索引,在一陣漫長的等待中,索引終於加上去了。 > `show status like 'thread%'` 索引加上去了之後,查看了一下當前Mysql的連線數,似乎沒有之前那麼高了,估計是擠壓的太多。 然後又查看了下伺服器的CPU佔用率,這次好了一點,從1%到80%來回跳動,沒有出現90&那麼高的頻率。 --- ## 總結 Mysql作為使用頻率非常高的資料庫,對於它的SQL調優真的是一門技術活,而且專案中的一些SQL看的也是想吐,這種調優起來真的難上加難。 其實 `information_schema` 這個資料庫,裡面的Mysql日誌看起來比業務日誌順眼的