MySQL的刷脏机制
文章目錄
- 緩沖池 Buffer Pool
- 刷臟頁的時機
- MySQL定時刷
- MySQL內存(buffer pool)不足的時候
- MySQL正常關閉的時候
- redo log滿了的時候
- 刷臟導致的性能問題
- 控制刷臟頁速度的因素
先了解下前置知識:
緩沖池 Buffer Pool
首先,對于InnoDB存儲引擎來說,數據都是放在磁盤上的,存儲引擎要操作數據,必須先把磁盤里面的數據加載到內存里面才可以操作。
??這里就有個問題,是不是我們需要的數據多大,我們就一次從磁盤加載多少數據到內存呢?比如我要讀6個字節。
??磁盤I/O的讀寫相對于內存的操作來說是很慢的。如果我們需要的數據分散在磁盤的不同的地方,那就意味著會產生很多次的I/O操作。
??所以,無論是操作系統也好,還是存儲引擎也好,都有一個預讀取的概念。也就是說,當磁盤上的一塊數據被讀取的時候,很有可能它附近的位置也會馬上被讀取到,這個就叫做局部性原理。那么這樣,我們干脆每次多讀取一點,而不是用多少讀多少。
??InnoDB設定了一個存儲引擎從磁盤讀取數據到內存的最小的單位,叫做頁。操作系統也有頁的概念。操作系統的頁大小一般是4K,而在InnoDB里面,這個最小的單位默認是16KB大小。如果要修改這個值的大小,需要清空數據重新初始化服務。
舉個例子,你去燒烤店跟老板說,老板,來一個生蠔。他根本不賣,懶得給你烤。老板賣給你生蠔,就是一打一打地賣。
??我們要操作的數據就在這樣的頁里面,數據所在的頁叫數據頁。
這里有一個問題,操作數據的時候,每次都要從磁盤讀取到內存(再返回給Server),有沒有什么辦法可以提高效率?
??還是緩存的思想。把讀取過的數據頁緩存起來。
??InnoDB設計了一個內存的緩沖區。讀取數據的時候,先判斷是不是在這個內存區域里面,如果是,就直接讀取,然后操作,不用再次從磁盤加載。如果不是,讀取后就寫到這個內存的緩沖區。
??這個內存區域有個專屬的名字,叫 Buffer Pool。
??修改數據的時候,也是先寫入到 buffer pool,而不是直接寫到磁盤。當數據在緩存中,也就是內存的數據頁和磁盤數據不一致的時候,我們把它叫做臟頁。那臟頁什么時候才同步到磁盤呢?
??InnoDB里面有專門的后臺線程把Buffer Pool的數據寫入到磁盤,每隔一段時間就一次性地把多個修改寫入磁盤,這個動作就叫做刷臟。
刷臟頁的時機
MySQL定時刷
MySQL會在自認為系統“空閑”的時候或者當系統更新很頻繁,redo log很快就寫滿的情況下,合理的定時進行刷臟
MySQL內存(buffer pool)不足的時候
當需要將數據頁讀到內存中時,發現內存不夠了,就需要淘汰掉內存中最不經常使用的數據頁,空出內存給別的數據頁使用,如果淘汰的是“臟頁”,就要先把臟頁寫到磁盤中。
MySQL正常關閉的時候
如果關閉的時候不刷臟,啟動的時候就需要去讀redo log然后同步數據到磁盤,這樣啟動速度會變慢。
redo log滿了的時候
redo log寫滿的時候,整個系統就不能再接收更新了,所有的更新必須都阻塞住。這種情況要盡量避免。
刷臟導致的性能問題
一個查詢要淘汰的臟頁個數太多,會導致查詢的相應時間明顯變長
日志寫滿,更新全部讀,寫性能跌為0,這種情況對敏感業務來說,是不能接受的
因此InnoDB要控制臟頁比例,來盡量避免這兩種情況
需要正確告訴InnoDB所在主機的IO能力,這樣InnoDB才能知道需要全力刷臟頁的時候,可以刷多快。
可以通innodb_io_capacity參數來控制InnoDB的刷盤能力,這個值建議設置成磁盤的IOPS,通過fio工具可以測試出磁盤的IOPS,命令如下:
innodb_io_capacity的默認值為200,正確配置innodb_io_capacity可以發揮機器的性能,錯誤配置也會導致性能問題,比如使用SSD的硬盤就可以將這個值配大些,但是也不能配置過大,配置過大會導致InnoDB把磁盤的能力全用來刷臟頁了,不能服務用戶請求。
控制刷臟頁速度的因素
如果刷臟頁慢,會導致內存臟頁太多,其次是redo log寫滿(因為臟頁還沒有同步到磁盤,redo log就不能覆寫)。
InnoDB的刷盤速度就通過臟頁比例和redo log寫盤速度來控制的.
為了減少刷臟給業務帶來的影響,要合理的設置innodb_io_capacity的值,并且平時要多關注臟頁比例,不要讓它經常解決75%。
--臟頁比例計算: select VARIABLE_VALUE into @a from performance_schema.global_status where VARIABLE_NAME = 'Innodb_buffer_pool_pages_dirty'; select VARIABLE_VALUE into @b from performance_schema.global_status where VARIABLE_NAME = 'Innodb_buffer_pool_pages_total'; select @a/@b;連帶機制
一旦一個查詢請求需要在執行過程中刷掉一個臟頁時,這個查詢就可能要比平時慢了,MySQL中的一個機制可能會讓查詢更慢。
在準備刷一個臟頁的時候,如果這個數據頁旁邊的數據頁剛好是臟頁,就會把這個“鄰居”也帶著一起刷掉,并且這個邏輯會繼續蔓延。
通過innodb_flush_neighbors可以控制這個行為,值為1的時候會有上述的連帶機制,MySQL8.0以下默認為1。
?
建議:
當使用的是機械硬盤時,建議開啟,這樣可以減少很多的隨機IO
當使用的是固態硬盤這類IOPS比較高的設備時,建議關閉,因為這個時候IOPS往往不是瓶頸,這樣可以減少SQL的響應時間
總結
以上是生活随笔為你收集整理的MySQL的刷脏机制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MOS管分析
- 下一篇: java计算机毕业设计建筑劳务监管平台源