天天看點

MySQL 資料庫救火:磁盤爆滿了,怎麼辦?

摘要:當磁盤空間爆滿後,MySQL會發生什麼事呢?又應該怎麼應對?

大多數使用者在對于磁盤進行分區的時候都是習慣性的不給系統盤預留很大空間,其實這并不是一個好習慣。因為系統分區并不像我們想象的那樣會僅僅安裝一個作業系統,系統分區多數還是會承載作業系統主要應用軟體安裝任務。那麼當磁盤空間爆滿後,MySQL會發生什麼事呢?又應該怎麼應對?

MySQL 資料庫磁盤爆的主要原因

資料量大

MySQL 磁盤爆的最常見原因之一就是資料量突然增大導緻資料庫爆,這種原因往往和業務相關。比如應用程式在短時間内生成了大量的資料,如果是突然出現新增大量資料,也有可能是某些測試用例或者壓測導緻。這種原因導緻的資料庫磁盤暴漲可以通過清理資料的方式解決,比如清除特定時間段的資料。

建議在測試環境等資料庫,進行壓力測試或者其他自動化測試時候對資料做特殊的标志,在完成測試後自動清除測試産生的垃圾資料,避免日積月來導緻磁盤爆滿影響資料庫使用。

同時按照資料庫日常使用的情況看是否需要對磁盤進行擴容,但是擴容隻能緩解,不能根治。

日志檔案

MySQL在日常運作的時候回産生大量的日志檔案,這些日志檔案也會占用磁盤空間,日積月累可能會産生幾百G的日志檔案。

MySQL 的日志檔案主要有以下幾種:

  • bin log 二進制檔案通常是占用空間最大的日志類型,這和資料庫的使用情況相關。
  • error 錯誤日志占用空間大的原因主要展現在長時間的日積月累,沒有定時清除導緻,比如運作了一兩年的資料庫,産生的錯誤日志往往也比較大。
  • 慢查詢日志 慢查詢日志通常不會占用太多空間,但是長時間不清理也會出現占用過多的問題,需要定時清理

臨時檔案

臨時檔案是資料庫運作時候産生的臨時性檔案,這種臨時性檔案在運作結束以後會自動釋放,但是某些異常情況下如果沒有釋放會造成比較嚴重的後果,比如短時間的慢查詢語句,這種慢查詢執行時間巨長,查詢的資料很多,MySQL在記憶體不夠的情況下回臨時将中間結果存放在資料庫的臨時目錄下。

處理日志檔案導緻的磁盤爆滿

清理日志檔案導緻的磁盤爆滿比較容易,在確定檔案備份轉存的前提下可以直接清理檔案。使用 echo ‘’ >> host- XXXXX.err 等指令可以直接清理這些日志檔案。

切記不要直接删除相關的日志檔案

檢視目前資料庫伺服器磁盤占用情況可以使用如下指令

df -h      
MySQL 資料庫救火:磁盤爆滿了,怎麼辦?

檢視某個檔案夾下的檔案磁盤占中情況可以使用 du 明令 參考

# 切換到需要檢視的路徑下使用
du -hl      

日志檔案導緻的磁盤爆滿可以通過linux 指令

echo '' >> host-xxxxx.log      

處理臨時檔案導緻的磁盤爆滿

檢視Mysql 配置的臨時目錄

通常 MySQL 的臨時目錄在 mysql/temp 路徑下,如果想檢視配置的參數,可以使用 show variables like ‘tmpdir’ SQL指令

show variables like 'tmpdir'      
MySQL 資料庫救火:磁盤爆滿了,怎麼辦?

臨時檔案産生的原因

臨時檔案産生的主要原因是MySQL在執行的時候,對一些大資料量的操作的時候記憶體無法滿足存儲需求的時候,MySQL會使用臨時檔案,比如某個臨時表查詢出的幾百萬資料,某個聯合查詢産生的結果集等。通常情況下MySQL産生的臨時檔案很小,同時也會及時釋放,但是一些異常情況下,比如慢查詢,會導緻短時間産生大量的臨時檔案。

下面是一個因為慢查詢導緻臨時目錄下産生大量檔案的案例。

臨時檔案産生過多導緻磁盤爆滿,造成資料庫短時故障

資料庫崩潰的前兆往往是短時間出現大量IO,CPU暴漲。出現以上征兆的時候資料庫就離崩潰不遠了,下面這個案例就是。

MySQL 資料庫救火:磁盤爆滿了,怎麼辦?

這個案例中我們發現在某個時間點資料庫突然CPU暴漲,而且是持續性暴漲,與此對應的磁盤的IO次數暴增,記憶體使用暴增。這個時候基本可以判斷資料庫出現了短時間大量的慢查詢。

為什麼慢查詢會導緻磁盤IO暴增?原因是上面說的,資料庫在查詢的時候使用的臨時表或者臨時資料如果記憶體不足以存放的時候,資料庫會将這些資料存放在磁盤中,随着慢查詢越來越多就會出現集中踩踏的問題,問題愈演愈烈,最終導緻資料庫卡頓或者崩潰。

MySQL 資料庫救火:磁盤爆滿了,怎麼辦?
MySQL 資料庫救火:磁盤爆滿了,怎麼辦?

上面案例中通過檢視資料庫執行記錄,我們發現的确出現了慢查詢積壓的情況,使用以下 SQL查詢 可以查詢目前正在執行的SQL狀态

SELECT id, `state`, user,host,time,`INFO` FROM information_schema.processlist where 
state IS NOT NULL  and state <> "" ORDER BY time desc;      
MySQL 資料庫救火:磁盤爆滿了,怎麼辦?

上面,你可以看到資料庫正在執行超過 10W秒的SQL,而且是好幾個,這樣就不難了解為什麼資料庫會出現短時間CPU 和IO暴增的情況。

解決這些問題的辦法就是: kill 目前的慢查詢,這個辦法很管用,但是要記錄查詢的語句和使用的登入賬号和機器,以備興師問罪。

下面這個語句可以快速生成批量 kill 語句。

SELECT concat('kill ', id, ';') FROM information_schema.processlist where user =
 'HispaceCMS' and  `COMMAND` = 'Query' and  state IS NOT NULL and state <> '' and DB is 
not null and time > 1000 ORDER BY time desc      

生成以後批量執行就可以了。執行完查詢磁盤占用情況,從96% 下降到 50左右。

MySQL 資料庫救火:磁盤爆滿了,怎麼辦?

​​點選關注,第一時間了解華為雲新鮮技術~​​