在最近release的5.7.6版本中又有了進一步的改進。
修改一、更精确的loop計算時間
page cleaner會每做srv_flushing_avg_loops次後,會去計算刷髒和redo lsn增長的速度。由于每次page cleaner的工作量是自适應的,一次flush操作的時間可能超過1秒,是以做n次loop的總時間可能超過n秒。
在新版本中,統一采用目前時間和上次計算速率時間差來确認是否需要重新計算速率。是以參數innodb_flushing_avg_loops的行為實際上等同于每這麼多秒後重計算速率。
修改二、根據buffer pool執行個體的髒頁分布來決定刷髒
我們知道從5.7版本開始支援多個page cleaner線程以實作并行刷髒。在5.7.6之前的版本中,page cleaner協調線程根據目前的負載情況,會計算出預計需要flush的總page數和目标lsn,然後在多個bp instance間做個均分。
考慮一種場景:如果bp執行個體間的負載不平衡,某個執行個體在目标lsn之前的髒頁很多,而有些執行個體很少,那麼應該多作刷髒動作的bp就可能産生堆積。 我們之前在webscalesql google公開讨論組有過類似的讨論,感興趣的可以看看。
回到正題上來,在5.7.6版本中,計算目标page數的方法大概如下:
#根據目前髒頁占比和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的百分比估算的總的page flush的量
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 instance:
如果目前有足夠的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的定值依然讓人很困惑,也許是官方測試的比較理想的配置。不過最好還是設定成可配置的,由使用者根據自己具體的負載情況來進行定制。
修改三、使用者線程在檢查redo 空間時不參與刷髒
當redo file中未做checkpoint的日志量過多時,在早期版本中中使用者線程會進行batch flush操作,将每個buffer pool instance的lsn推進到某個指定的lsn。如果某個bp instance已經有别的線程在flush,則跳過嘗試下一個instance,同時認為這次的flush操作是失敗的,會傳回重試。
當使用者線程參與到刷髒時,通常會認為這是個性能拐點,tps會出現急劇下降,大量線程陷入condtion wait。是以在5.7.6裡,當使用者線程需要推進lsn時,不再主動發起刷髒,而是輪詢每個bp instance,直到所有的bp instance 的lsn超過其目标lsn,每次輪詢預設sleep重試時間為10000微妙
事實上, percona server在5.6版本裡已經使用相同的政策了。
修改四、為page cleaner線程設定更高的優先級
在linux平台下,對于page cleaner的協調線程和worker線程,其cpu優先級被設定為-20,即最高優先級,通過函數set_priority設定。目前還不支援參數配置
修改五、防止checkpoint lsn被覆寫
在之前的版本中,盡管每次在寫redo時,都會去檢察redo檔案是否容留了足夠百分比的可用空間,但實際上并沒有考慮即将寫入到的redo log長度。如果我們操作一些極大的記錄時,産生很長的redo log記錄,可能導緻檢查點lsn被覆寫掉,造成不能做安全的crash recovery。
在新的邏輯裡,在檢測到目前寫入的redo 可能造成覆寫檢察點時,就會sleep等待page cleaner線程刷髒,并做redo log checkpoint。直到checkpoint的lsn推進到安全的位置。
除了上述幾點外,還加入了更豐富的監控項