MySQL的刷脏页策略
1. MySQL的日志
這篇文章主要以InnoDB引擎為例。
在MySQL的InnoDB當中,有兩個重要日志模塊,一個是redo log(重做日志) 一個是binlog(歸檔日志) 。
redo log的好處
1.當我們修改一條數據時,如果數據在內存中,我們是先會去改內存的,而不是先去改磁盤。假如數據都在內存中,這時候斷電了怎么辦,服務器宕機怎么辦,這個時候就需要我們的redo log了。
2.redo只是記錄了對數據的修改,數據會比一頁數據小得多。大大減少了IO頻率。并且想比于更新操作,更新過程是在磁盤上隨機IO,費時。 而寫redo log 是在磁盤上順序IO。效率要高。
在每一條數據更新時,MySQL會先寫redo log日志,在去寫binlog 日志。在寫這兩個日志過程中會涉及到兩階段提交。他可以保證兩個日志邏輯上的一致性。所以即使因為停電,宕機等原因,MySQL也可以通過redo log將數據進行恢復。
兩者區別
redo log 是物理日志,記錄的是“在某個數據頁上做了什么修改”;binlog 是邏輯日志,記錄的是這個語句的原始邏輯,比如“給 ID=10 這一行的 c 字段加 10 ”。
redo log 是循環寫的,空間固定會用完; binlog 是可以追加寫入的。“追加寫”是指 binlog 文件寫到一定大小后會切換到下一個,并不會覆蓋以前的日志。
有了redlog,為什么還要有binglog
一個原因是,redolog只有InnoDB有,別的引擎沒有。另一個原因是,redolog是循環寫的,不持久保存,binlog的“歸檔”這個功能,redolog是不具備的。
redo log 是循環寫的,固定空間用完會怎么辦?這個也就是下面也會帶著大家去了解的MySQL的刷臟頁策略。
2.緩沖池(buffer pool)
buffer pool 是數據庫的一個內存組件,里面緩存了磁盤上的真實數據,Java系統對數據庫的增刪改操作,主要是這個內存數據結構中的緩存數據執行的。
MySQL的InnoDB能使用內存會盡量的使用內存。這樣是為了加速數據訪問,把查詢數據放在MySQL作為一個存儲系統,使用緩沖池(buffer pool)機制,以避免每次查詢數據都進行磁盤IO。
它的默認大小是128M。在實際的生產環境中可以通過參數innodb_buffer_pool_size對 buffer pool進行調整
關于緩沖池大家可以參考這篇文章去深入了解:緩沖池(buffer pool),這次徹底懂了!!!
3.什么時候會刷臟頁
什么是臟頁
當內存數據頁跟磁盤數據頁內容不一致的時候,我們稱這個內存頁為“臟頁”。
什么是干凈頁
內存數據寫入到磁盤后,內存和磁盤上的數據頁的內容就一致了,稱為“干凈頁”
MySQL什么時候會刷臟頁
(1)redo log滿了
因為我們redo log日志是有固定空間的,如果它滿了的話,就會進行刷臟頁 (flush 臟頁)。MySQL會先把內存數據更新到磁盤上,并把redo log進行清空。這種情況是 InnoDB所有更新會為0,因為出現這種情況的時候,整個系統就不能再接受更新了,所有的更新都必須堵住。
(2)內存滿了
因為我們MySQL的緩沖池是有固定內存大小的,當我們緩沖池滿了的時候,這時候也會進行刷臟頁。而這時在內存中的數據會有三種類型數據頁
第一種是,還沒有使用的; 第二種是,使用了并且是干凈頁;第三種是,使用了并且是臟頁。
而當要讀入的數據頁沒有在內存的時候,就必須到緩沖池中申請一個數據頁。這時候只能把最久不使用的數據頁從內存中淘汰掉:如果要淘汰的是一個干凈頁,就直接釋放出來復用;但如果是臟頁呢,就必須將臟頁先刷到磁盤,變成干凈頁后才能復用。
(3)mysql空閑的時候
這個時候就是我們MySQL比較空閑,沒有請求的時候。這個時候redo log會flush 臟頁,會把內存中的臟頁更新到我們的磁盤里。
(4)mysql正常關閉的時候
因為我們MySQL正常關閉,肯定是要把內存臟頁更新到磁盤中的。
會影響性能的刷臟頁操作
1.比如我們一個查詢要淘汰的臟頁個數太多,如果MySQL刷臟頁速度很慢,則會導致查詢的響應時間明顯變長;
2.redo log 寫滿了,導致這個系統更新為0;
4.刷臟頁控制策略
1.設置系統刷臟頁的速度和能力
show global variables like ‘innodb_io_capacity’; 查看當前系統刷臟頁的能力
set global innodb_io_capacity=200; 進行設置刷臟頁速度
2.設置臟頁比例
如果我們系統一直全力去刷盤的話,那其他業務必定會受到影響。所以我們需求設置臟頁比例,去執行刷盤。臟頁比例默認75%,一定不要讓其接近75%**
查看當前臟頁比例
參數innodb_max_dirty_pages_pct是臟頁比例上限,默認值是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;
3. 刷臟頁速度 nnodb_io_capacity定義的能力乘以R%(redolog)來控制刷臟頁的速度
InnoDB每次寫入的日志都有一個序號,當前寫入的序號跟checkpoint對應的序號之間的差值,InnoDB會將這兩個值經過一定的計算得出一個數,這個結果數就是用來控制刷臟頁的速度。
4. innodb_flush_neighbors=0(不開啟臟頁相鄰淘汰) (對于機械硬盤順序讀寫會有提升,ssd無提升。iops普通機械硬盤只有幾百,ssd有上千,可以不開啟)
在MySQL 8.0中,innodb_flush_neighbors參數的默認值已經是0了。
總結
以上是生活随笔為你收集整理的MySQL的刷脏页策略的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 推荐五款好用的项目管理系统
- 下一篇: SQL存储过程来调用webservice