也說快速關閉MySQL/InnoDB

http://www.orczhou.com/index.php/2010/12/more-about-mysql-innodb-shutdown/


如果用的引擎是InnoDB,每次敲下mysqladmin -uroot -p shutdown關閉數據庫的時候,總是很難預測這個命令會執行多久,實際經驗表明,短則五秒,長則三十分鐘一小時都有可能。也分享一下我的經驗吧。

1. 爲什麼InnoDB關閉會慢?

事實上,並不是每次關閉InnoDB都很慢的。Why?InnoDB較之MyISAM,一個重要特性是InnoDB會在內存中開闢一個Buffer Pool來存儲最近訪問的數據塊/索引塊,使得下次再次訪問這個塊時速度能夠很快。當InnoDB對需要修改數據塊的時候,會先記錄修改日誌,然後直接對Buffer_Pool中的數據塊的操作。記錄日誌是順序寫,對數據塊的操作是內存操作,這讓InnoDB在很多場景下有這很好的速度優勢。

上面對內存塊修改完成後,InnoDB就向客戶端返回了。可這時實際磁盤上的數據塊,還並沒有被更新,我們把這樣的page稱爲Dirty Page。在InnoDB的後臺有一個專門的線程來做將內存數據塊Flush到磁盤的工作。這個Flush操作就是主要影響InnoDB關閉時間的因素。在關閉MySQL/InnoDB時,所有的Dirty_Page都需要Flush,所以Dirty_Page越多,要Flush的數據塊也就越多,意味着InnoDB關閉時間越長

我們可以通過下面的命令來觀察Dirty Page的數量:

mysqladmin -uroot ext -i 1 |grep "Innodb_buffer_pool_pages_dirty"


2. 參數innodb_max_dirty_pages_pct


Buffer_Pool中Dirty_Page所佔的數量,直接影響InnoDB的關閉時間。參數innodb_max_dirty_pages_pct可以直接控制了Dirty_Page在Buffer_Pool中所佔的比率,而且幸運的是innodb_max_dirty_pages_pct是可以動態改變的。

所以,在關閉InnoDB之前先將innodb_max_dirty_pages_pct調小,強制數據塊Flush一段時間,則能夠大大縮短MySQL關閉的時間。

set global innodb_max_dirty_pages_pct=0;


一般執行了上面的命令之後,Dirty_Page的Flush仍需要一段時間,所以要稍等一會兒,再關閉MySQL纔有效果。

3. 關閉前做些什麼

有時候,就算你改變innodb_max_dirty_pages_pct=0,仍然不能保證InnoDB快速關閉。還有一些注意事項。

設置數據庫爲只讀:如果數據庫一直是活躍的,有連接在向裏面寫數據,那麼Dirty Page則還可能不斷的產生。

如果是備庫,在innodb_max_dirty_pages_pct設置成0的同時,最好先stop slave:這個很關鍵,而且對關閉時間影響也會很大。第一,主動stop slave後,MySQL在關閉時,需要停止的線程其實是更少了的。第二,如果slave的SQL線程還在執行的話,Buffer Pool則還在活動,Dirty Page也可能還會不斷的增多。

一般,如果注意到了上面三點:

set global innodb_max_dirty_pages_pct=0

set global read_only=1

stop slave


關閉數據庫,就會很快了。如果你把上面三步做完,然後觀察Dirty Page的數量,當數量很少時,再執行命令關庫,這樣總能保證以較快的速度完成關庫命令。

4. 一個注意事項

這裏需要注意的是,你不需等到Dirty Page的數量到零,纔開始關閉MySQL。因爲有時候,即使已經沒有活動的會話時,InnoDB的Insert Buffer的合併仍然會產生一些Dirty Page,所以這時你可能會發現,等了很久很久很久Dirty Page的數量仍然大於零。

其實這時,你已經可以快速的關閉數據庫了。我怎麼判斷這種情況呢?這時我們可以通過InnoDB的LSN來判斷,下面是SHOW InnoDB Status裏面獲取的信息:

Log sequence number 814 3121743145
Log flushed up to   814 3121092043
Last checkpoint at  814 2826361389

這裏看到,當前的LSN是814 3121743145,最後一個檢查點在814 2826361389,也就是說兩者相差了3121743145-2826361389=295381756,那麼意味着InnoDB還有很多Dirty Page需要Flush。

下面是另一個庫的LSN信息:

Log sequence number 0 1519256161
Log flushed up to   0 1519256161
Last checkpoint at  0 1519256161

可以看到,這裏的Dirty Page都已經Flush了,那麼關閉InnoDB也就很快了。

一般,並不需要等到最後檢查點和當前LSN相等才關閉,兩者只要相差不多(<1000)關閉起來就很快了。

5. 最後再羅嗦一下

我這個人寫博客很羅嗦的,各位看官在忍耐一下吧。

其實,像上面這樣折騰,整個關庫的過程有可能並不比你直接執行mysqladmin -uroot shutdown快,但是執行上面的步驟,會讓你清楚關庫到底與多久,可以讓你的關庫命令能夠在一個可以預期的時間內完成。簡單的說,會讓關庫的時間心裏有個底。

當你希望一切都心裏有底的時候,那你就需要注意上面提到的一些細節。

參考文檔

1. How to decrease InnoDB shutdown times

2. 測試快速關閉innodb的方法

3. MySQL/InnoDB Manual


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章