1. 程式人生 > >【MySQL技術內幕】10-啟動關閉與恢復

【MySQL技術內幕】10-啟動關閉與恢復

InnoDB是 MySQL資料庫的儲存引擎之一,因此 InnoDB儲存引擎的啟動和關閉,更準確的是指在 MySQL例項的啟動過程中對 InnoDB儲存引擎的處理過程。 在關閉時,引數 innodb fast shutdown影響著表的儲存引擎為 InnoDB的行為該引數可取值為0、1、2,預設值為1。

  • 0表示在 MySQL資料庫關閉時, InnodB需要完成所有的 full purge和 merge insert buffer,並且將所有的髒頁重新整理回磁碟。這需要一些時間,有時甚至需要幾個小時來完成。如果在進行 InnoDB升級時,必須將這個引數調為0,然後再關閉資料庫。
  • 1是引數 innodb fast shutdown的預設值,表示不需要完成上述的 full purge和merge insert buffer操作,但是在緩衝池中的一些資料髒頁還是會重新整理回磁碟。
  • 2表示不完成 full purge和 merge insert buffer操作,也不將緩衝池中的資料髒頁寫回磁碟,而是將日誌都寫入日誌檔案。這樣不會有任何事務的丟失,但是下次MySQL資料庫啟動時,會進行恢復操作( recovery)。

當正常關閉 MySQL資料庫時,下次的啟動應該會非常“正常”。但是如果沒有正常地關閉資料庫,如用k命令關閉資料庫,在 MySQL資料庫執行中重啟了伺服器,或者在關閉資料庫時,將引數 innodb fast shutdown設為了2時,下次 MySQL資料庫啟動時都會對 InnoDB儲存引擎的表進行恢復操作。 引數 innodb force recovery影響了整個 InnoDB儲存引擎恢復的狀況。該引數值預設為0,代表當發生需要恢復時,進行所有的恢復操作,當不能進行有效恢復時,如資料頁發生了 corruption, MySQL資料庫可能發生宕機( crash),並把錯誤寫入錯誤日誌中去。

但是,在某些情況下,可能並不需要進行完整的恢復操作,因為使用者自己知道怎麼進行恢復。比如在對一個表進行 alter table操作時發生意外了,資料庫重啟時會對InnoDB表進行回滾操作,對於一個大表來說這需要很長時間,可能是幾個小時。這時使用者可以自行進行恢復,如可以把表刪除,從備份中重新匯入資料到表,可能這些操作的速度要遠遠快於回滾操作。 引數 innodb force recovery還可以設定為6個非零值:1~6。大的數字表示包含了前面所有小數字表示的影響。具體情況如下:

  • 1( SRV_FORCE_IGNORE_CORRUPT):忽略檢查到的 corrupt頁。
  • 2( SRV_FORCE_NO_BACKGROUND):阻止 Master Thread執行緒的執行,如 Master Thread執行緒需要進行 full purge操作,而這會導致 crash
  • 3( SRV_FORCE_NO_TRX_UNDO):不進行事務的回滾操作。
  • 4( SRV_FORCE_NO_IBUF_MERGE):不進行插入緩衝的合併操作。
  • 5( SRV_FORCE_NO_UNDO_LOG_SCAN):不檢視撤銷日誌( Undo log), InnoDB儲存引擎會將未提交的事務視為已提交。
  • 6( SRV_FORCE_NO_LOG_REDO):不進行前滾的操作。

需要注意的是,在設定了引數 innodb_force_recovery大於0後,使用者可以對錶進行select、 create和drop操作,但 Insert、 update和 delete這類DML操作是不允許的現在來做一個實驗,模擬故障的發生。在第一個會話中( session),對一張接近1000萬行的 InnoDB儲存引擎表進行更新操作,但是完成後不要馬上提交:

mysql>START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
mysql>UPDATE profile set password='';
Query OK, 9587770 rows affected (7 min 55.73 sec)
Rows matched: 9999248 Changed: 9587770 Warnings: 0

START TRANSACTION語句開啟了事務,同時防止了自動提交( auto commit)的發生, UPDATE操作則會產生大量的UNDO日誌( undo log)。這時,人為通過kt命令殺掉 MySQL資料庫伺服器。

通過kill命令可以模擬資料庫的宕機操作。下次 MySQL資料庫啟動時會對之前的UPDATE事務進行回滾操作,而這些資訊都會記錄在錯誤日誌檔案(預設字尾名為.err中。如果査看錯誤日誌檔案,可得如下結果:

可以看到,採用預設的策略,即將 innodb force recovery設為0, InnoDB會在每次啟動後對發生問題的表進行恢復操作。通過錯誤日誌檔案,可知這次回滾操作需要回滾8867280行記錄,差不多總共進行了9分鐘。 再做一次同樣的測試,只不過這次在啟動 MySQL資料庫前,將引數 innodb_force_recovery設為3,然後觀察 InnoDB儲存引擎是否還會進行回滾操作。檢視錯誤日誌檔案,可得: 這裡出現了“!!!" InnoDB警告已經將 innodb force recovery設定為3,不會進行回滾操作了,因此資料庫很快啟動完成了。但是使用者應該小心當前資料庫的狀態,並仔細確認是否不需要回滾事務的操作。