LRU 算法前端
優化 LRU 算法算法
爲何採用優化 LRU 算法數據庫
應用背景後端
若是每一次一個頁發生變化,就當即刷新到磁盤,那麼開銷是很是大的。若是在從緩衝池將頁的新版本刷新到磁盤時發生了宕機,那麼數據就不能恢復了。異步
當前事務數據庫廣泛採用write ahead log 策略,當事務提交時,先寫重作日誌,再修改頁。這也是事務中持久性的要求。性能
主要解決如下問題優化
縮短數據庫的恢復時間;設計
緩衝池不夠用時,將髒頁刷新到磁盤;日誌
重作日誌不可用時,刷新髒頁。code
當數據庫發生宕機時,不須要重作全部日誌,由於checkpoint 以前的頁都刷新到磁盤了。這樣就縮短了恢復的時間。此外,當緩衝池不夠用時,根據LRU 算法回溢出最少使用的頁,而後對其強制執行checkpoint,刷新到磁盤。
checkpoint 的時間,條件,髒頁的選擇都是很是複雜的。好比每次刷新多少頁,從哪裏取髒頁,什麼時間觸發checkpoint。InnoDB 提供了兩種checkpoint選擇:
sharp 發生在數據庫關閉時,默認將全部髒頁都刷新到磁盤。
fuzzy 發生在運行時,只刷新一部分髒頁。刷新是異步的。
在InnoDB中,主鍵是惟一的行標識。所以,插入彙集索引通常都是順序的,不須要磁盤的隨機讀取。不過非彙集索引其插入和索引都是隨機的。
固然,B+樹的特性決定了非彙集索引的插入的離散性。由於數據頁所在的葉子節點是按照邏輯順序離散存放的。
InnoDB存儲引擎開創性地設計了Insert Buffer(插入緩衝),對於非彙集索引的插入或更新操做,不是每一次直接插入到索引頁中,而是先判斷插入的非彙集索引頁是否在緩衝池中,若在,則插入到緩衝池中的非彙集索引頁;若不在,則先放入到一個Insert Buffer對象中,好似欺騙。
數據庫這個非彙集的索引沒有直接插到葉子節點,只是存放在另外一個位置。而後再以必定的頻率和狀況進行插入 Insert Buffer 和輔助索引頁子節點的merge(合併)操做,一般能將多個插入合併到一個操做中(由於在一個索引頁中),這就大大提升了對於非彙集索引插入的性能。
然而Insert Buffer的使用須要同時知足如下兩個條件:
當知足以上兩個條件時,InnoDB存儲引擎會使用 Insert Buffer,這樣就能提升插入操做的性能了。不過考慮這種狀況:
所以須要一個副本,當寫入失效時,先經過頁的副本還原該頁,這就是double write。
默認狀況下全部頁的刷新首先放入到 double write中。