1. 程式人生 > >磁盤空間滿了之後MySQL會怎樣

磁盤空間滿了之後MySQL會怎樣

bsp erp 無法 status auto 一個 並不會 每分鐘 查看

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

技術分享

  會發生什麽事

  當磁盤空間寫滿了之後,MySQL是無法再寫入任何數據的,包括對表數據的寫入,以及binlog、binlog-index等文件。

  當然了,因為InnoDB是可以把臟數據先放在內存裏,所以不會立刻表現出來無法寫入,除非開啟了binlog,寫入請求才會被阻塞。

  當MySQL檢測到磁盤空間滿了,它會怎麽樣呢?下面我們來看一個具體例子:

  磁盤滿了之後MySQL會做什麽?

  我們看下官方的說法

技術分享

  其實MySQL本身並不會做任何操作,如官方文檔說說,只會每分鐘check一次是否有空閑空間,並且10分鐘寫一次錯誤日誌。

  但是再次期間由於磁盤滿了,意味著binlog無法更新,redolog也無法更新,所有bufferpool中的數據無法被flush上,如果不幸的服務器重啟,或者實例被kill了,那必然會造成數據丟失,這幾乎是一定的。所以,處理磁盤滿的問題最好是先釋放出來一定空間讓dirty數據刷新下來。

  磁盤滿了為什麽會導致操作hang住?

  1、select

  首先經過經驗和實際測試,select操作不會由於磁盤滿導致問題,也就是所有select操作都會正常運行。

  2、insert

  經過不通的測試發現,當磁盤滿了之後,並不是第一個insert就卡住,而是會在n個之後出現卡住的情況。

  通過查看error日誌,發現卡住現象和刷磁盤的操作有關系。

技術分享

  為了驗證推論是否正確,我們將sync_binlog設置為1,在這種情況下,insert第一條就卡住了,並且errorlog中直接報錯提示寫binlog失敗。看來卡住確實和刷磁盤有關系。

  目前已知和刷磁盤有關系的參數有3個,分別是sync_binlog,innodb_flush_log_tr_commit,和duoblewrite。

  3、showslavestatus

  在從庫經過測試,操作會被卡住,這主要是由於執行showslavestatus需要獲得LOCK_active_mi鎖,然後鎖上mi->data_lock,但是由於磁盤滿了無法將io_thread中的數據寫入到relaylog中,導致io_thread持有mi->data_lock鎖,這就導致了死鎖。

  所以,這就導致在磁盤滿的情況下,執行showslavestatus操作會卡住。

  4、showstatus

  測試可以正常操作,但是如果先執行了showslavestatus操作的情況下,showstatus也會被卡住。這是因為執行showstatus需要鎖上LOCK_status,而由於status狀態中包含slavestatus,所以還需要鎖上LOCK_active_mi。如果限制性了showslavestatus,這時候由於mi->data_lock死鎖問題,導致io_thread不會釋放LOCK_active_mi鎖。這時候就導致showstatus和showslavestatus爭搶同一把LOCK_active_mi鎖,也形成了死鎖。

  所以,在磁盤滿的情況下,如果先執行showslavestatus,後執行showstatus,連個操作都會卡住。

  應該怎麽辦

  那麽,當發現磁盤空間滿了之後,我們應該怎麽處理呢,建議:

  每分鐘:檢查空間是否得到釋放,以便寫入新數據。當發現有剩余空間了,就會繼續寫入數據,一切照舊。

  每十分鐘:如果還是發現沒剩余空間,則會在日誌中寫入一條記錄,報告磁盤空間滿(這時候只寫入幾個字節還是夠的)。

  提高監控系統檢測頻率,預防再次發生;

  及時刪除不用的文件,釋放空間;

  若有線程因磁盤滿的問題被阻塞了,可先殺掉,等到下一分鐘重新檢測時它可能又可以正常工作了;

  可能因磁盤滿導致某些線程被阻塞,引發其他線程也被阻塞,可把導致阻塞的線程殺掉,其他被阻塞的線程也就能繼續工作了。

  例外

  有個例外的情況是:

  當執行REPAIRTABLE或者OPTIMIZETABLE操作時,或者執行完LOADDATAINFILE或ALTERTABLE之後批量更新索引時,這些操作會創建臨時文件,當執行這些操作過程中mysqld發現磁盤空間滿了,就會把這個涉及到的表標記為crashed,刪掉臨時文件(除了ALTERTABLE操作,MySQL會放棄正在執行的操作,刪除臨時文件,釋放磁盤空間)。

  備註:當執行這些命令過程中mysqld進程被意外被殺掉的話,其所生成臨時文件不會自動刪除,需要手工刪掉才能釋放磁盤空間。

磁盤空間滿了之後MySQL會怎樣