MYSQL 髒頁刷新

起因
昨天看了CSDN推送的一篇《騰訊面試:一條SQL語句執行得很慢的原因有哪些?》

裏面主要提到了
1.數據庫在刷新髒頁的時候會導致SQL很慢
2.鎖的問題
3.sql本身的問題

下面主要對刷髒頁理解,自己總結下

mysql 刷髒塊的幾種情況
1.redo日誌切換

2.buffer pool不足

3.mysql 自己覺得空閒

4.mysql正常關機

上面的3,4兩種情況可以忽略他們對性能的印象。

而 1,2兩種情況都有可能會影響mysql整體的性能,其實兩種情況的原因是一樣的,刷髒頁會佔用大量的IO資源,會影響到你其他的sql。

第一種情況,redo寫滿了需要覆蓋,覆蓋前需要filush沒有被寫入磁盤的髒頁,這種情況是要儘量的避免的,因爲這種情況出現,整個系統會不在DML。在5.6之前可能還會阻塞查詢。

第二中情況,內存不夠了,需要爲查詢或者更新騰出對應的空閒頁,這種情況很常見。

上面還會涉及很多的東西,比如檢查點,LRU LIST,FLUSH LIST,FREE LIST .

影響
主要兩個方面:

1.innodb_max_dirty_pages_pct

2.innodb_io_capacity

3.innodb_adaptive_flushing(不建議關閉)

InnoDB uses an algorithm to estimate the required rate of flushing, based on the speed of redo log generation and the current rate of flushing. The intent is to smooth overall performance by ensuring that buffer flush activity keeps up with the need to keep the buffer pool “clean”. Automatically adjusting the rate of flushing can help to avoid sudden dips in throughput, when excessive buffer pool flushing limits the I/O capacity available for ordinary read and write activity.

InnoDB uses its log files in a circular fashion. Before reusing a portion of a log file, InnoDB flushes to disk all dirty buffer pool pages whose redo entries are contained in that portion of the log file, a process known as a sharp checkpoint. If a workload is write-intensive, it generates a lot of redo information, all written to the log file. If all available space in the log files is used up, a sharp checkpoint occurs, causing a temporary reduction in throughput. This situation can happen even if innodb_max_dirty_pages_pct is not reached.

上面的意思就是mysql會使用一個算法來根據磁盤的IO能力和髒頁數量等來計算對髒頁的刷新,當然在大量的寫的情況下,影響性能也是不可避免的。

計算爲:

根據當前髒頁佔比和Redo LSN增長狀態,計算利用IO Capacity的百分比(pct_total)計算目標LSN:

根據當前髒頁佔比和Redo LSN增長狀態,計算利用IO Capacity的百分比(pct_total)

計算目標LSN:

target_lsn = oldest_lsn + lsn_avg_rate * buf_flush_lsn_scan_factor

其中oldest_lsn表示當前buffer pool中最老page的LSN,lsn_avg_rate表示每秒LSN推進的平均速率,buf_flush_lsn_scan_factor目前是hardcode的,值爲3。

統計每個buffer pool 小於target_lsn的page數pages_for_lsn

初步估定每個bp instance 的n_pages_requested= pages_for_lsn /buf_flush_lsn_scan_factor。每個bp的pages_for_lsn被累加到sum_pages_for_lsn

同時根據io capacity估算總的需要flush的Page數量:

sum_pages_for_lsn /= buf_flush_lsn_scan_factor;
n_pages = (PCT_IO(pct_total) + avg_page_rate + sum_pages_for_lsn) / 3;

n_pages若超過innodb_io_capacity_max,則設置爲innodb_io_capacity_max

輪詢每個Buffer pool 實例:
如果當前有足夠的Redo 空間:n_pages_requested  = n_pages / srv_buf_pool_instances
否則:n_pages_requested = n_pages_requested  * n_pages / sum_pages_for_lsn
也就是說,在Redo 空間足夠時,依然採用均衡的刷髒邏輯。

在早期版本中,會根據兩個條件來判斷每個bp刷髒的進度:目標LSN及page數。而到了5.7.6版本里,大多數情況下只根據更加準確的請求刷page數來進行判定 (系統空閒時進行100% io capactiy的page flush、崩潰恢復時、以及實例shutdown時的刷髒除外)

雖然計算公式比較清晰,但有些factor的定值依然讓人很困惑,也許是官方測試的比較理想的配置。不過最好還是設置成可配置的,由有經驗的用戶根據自己具體的負載情況來進行定製

上面的innodb_io_capacity 參數也變得尤其重要。一般可以設置爲磁盤的IOPS

還需要關注髒頁的比例,(Innodb_buffer_pool_pages_dirty/Innodb_buffer_pool_pages_total)

mysql> select VARIABLE_VALUE from performance_schema.global_status where VARIABLE_NAME = 'Innodb_buffer_pool_pages_dirty';
+----------------+
| VARIABLE_VALUE |
+----------------+
| 12634             |
+----------------+
1 row in set (0.00 sec)

mysql> select VARIABLE_VALUE  from performance_schema.global_status where VARIABLE_NAME = 'Innodb_buffer_pool_pages_total';
+----------------+
| VARIABLE_VALUE |
+----------------+
| 655280         |
+----------------+
1 row in set (0.00 sec)


Page cleaner thread是5.6.2引入的一個新線程,它實現從master線程中卸下緩衝池刷髒頁的工作;爲了進一步提升擴展性和刷髒效率,在5.7.4版本里引入了多個page cleaner線程,從而達到並行刷髒的效果。
目前Page cleaner並未和緩衝池綁定,有一個協調線程 和 多個工作線程,協調線程本身也是工作線程。工作隊列長度爲緩衝池實例的個數,使用一個全局slot數組表示
 

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