MySQL之Innodb引擎的4大特性
面試官:你了解MySQL的Inodb四大特性嗎?
1.插入緩沖 (Insert Buffer/Change Buffer)
插入緩存之前版本叫insert buffer,現版本 change buffer,主要提升插入性能,change buffer是insert buffer的加強,insert buffer只針對insert有效,change buffering對insert、delete、update(delete+insert)、purge都有效。有什么用呢?
對于非聚集索引來說,比如存在用戶購買金額這樣一個字段,索引是普通索引,每個用戶的購買的金額不相同的概率比較大,這樣導致可能出現購買記錄在數據在數據里的排序可能是1000,3,499,35…,這種不連續的數據,一會插入這個數據頁,一會插入那個數據頁,這樣造成的IO是很耗時的,所以出現了Insert Buffer。
Insert Buffer是怎么做的呢?mysql對于非聚集索引的插入,先去判斷要插入的索引頁是否已經在內存中了,如果不在,暫時不著急先把索引頁加載到內存中,而是把它放到了一個Insert Buffer對象中,臨時先放在這,然后等待情況,等待很多和現在情況一樣的非聚集索引,再和要插入的非聚集索引頁合并,比如說現在Insert Buffer中有1,99,2,100,合并之前可能要4次插入,合并之后1,2可能是一個頁的,99,100可能是一個頁的,這樣就減少到了2次插入。這樣就提升了效率和插入性能,減少了隨機IO帶來性能損耗。
綜合上述,Insert Buffer 只對于非聚集索引(非唯一)的插入和更新有效,對于每一次的插入不是寫到索引頁中,而是先判斷插入的非聚集索引頁是否在緩沖池中,如果在則直接插入;若不在,則先放到Insert Buffer 中,再按照一定的頻率進行合并操作,再寫回disk。這樣通常能將多個插入合并到一個操作中,目的還是減少了隨機IO帶來性能損耗。
使用插入緩沖的條件:
- 非聚集索引
- 非唯一索引
innodb_change_buffer設置的值有:
all: 默認值,緩存insert, delete, purges操作 none: 不緩存 inserts: 緩存insert操作 deletes: 緩存delete操作 changes: 緩存insert和delete操作 purges: 緩存后臺執行的物理刪除操作可以通過參數控制其使用的大小:
mysql> show variables like 'innodb_change_buffer_max_size'; +-------------------------------+-------+ | Variable_name | Value | +-------------------------------+-------+ | innodb_change_buffer_max_size | 25 | +-------------------------------+-------+ 1 row in set (0.05 sec)innodb_change_buffer_max_size,默認是25%,即緩沖池的1/4。最大可設置為50%。當MySQL實例中有大量的修改操作時,要考慮增大innodb_change_buffer_max_size
上面提過在一定頻率下進行合并,那所謂的頻率是什么條件?
1)輔助索引頁被讀取到緩沖池中。正常的select先檢查Insert Buffer是否有該非聚集索引頁存在,若有則合并插入。
2)輔助索引頁沒有可用空間。空間小于1/32頁的大小,則會強制合并操作。
3)Master Thread 每秒和每10秒的合并操作。
2.雙寫機制(Double Write)
在InnoDB將BP中的Dirty Page刷(flush)到磁盤上時,首先會將(memcpy函數)Page刷到InnoDB tablespace的一個區域中,我們稱該區域為Double write Buffer(大小為2MB,每次寫入1MB,128個頁,每個頁16k,其中120個頁為后臺線程的批量刷Dirty Page,還有8個也是為了前臺起的sigle Page Flash線程,用戶可以主動請求,并且能迅速的提供空余的空間)。在向Double write Buffer寫入成功后,第二步、再將數據分別刷到一個共享空間和真正應該存在的位置。
MySQL可以根據redolog進行恢復,而mysq在恢復的過程中是檢查page"的checksum, checksum就是pgae的最后事務號,發生partial page write問題時. DageR經損壞,找不到該page中的事務號就無法恢復。
具體的流程如下圖所示:
在不同的寫入階段,操作系統crash后,double write帶來的保護機制:
階段一:copy過程中,操作系統crash,重啟之后,臟頁未刷到磁盤,但更早的數據并沒有發生損壞,重新寫入即可
階段二:write到共享表空間過程中,操作系統crash,重啟之后,臟頁未刷到磁盤,但更早的數據并沒有發生損壞,重新寫入即可
階段三:write到獨立表空間過程中,操作系統crash,重啟之后,發現:
(1)數據文件內的頁損壞:頭尾checksum值不匹配(即出現了partial page write的問題)。從共享表空間中的doublewrite segment內恢復該頁的一個副本到數據文件,再應用redo log;
(2)若頁自身的checksum匹配,但與doublewrite segment中對應頁的checksum不匹配,則統一可以通過apply redo log來恢復。
階段X:recover過程中,操作系統crash,重啟之后,innodb面對的情況同階段三一樣(數據文件損壞,但共享表空間內有副本),再次應用redo log即可。
3.自適應哈希索引(Adaptive Hash Index,AHI)
哈希算法是一種非常快的查找方法,在一般情況(沒有發生hash沖突)下這種查找的時間復雜度為O(1)。InnoDB存儲引擎會監控對表上輔助索引頁的查詢。如果觀察到建立hash索引可以提升性能,就會在緩沖池建立hash索引,稱之為自適應哈希索引(Adaptive Hash Index,AHI)。
自適應哈希索引由innodb_adaptive_hash_index 變量啟用,AHI是通過緩沖池的B+ Tree構造而來,使用索引鍵的前綴來構建哈希索引,前綴可以是任意長度。InnoDB存儲引擎會自動根據訪問的頻率和模式來自動地為某些熱點頁建立hash索引。加快索引讀取的效果,相當于索引的索引,幫助InnoDB快速讀取索引頁。
根據InnoDB官方文檔說明,啟用了AHI后,讀寫的速度會提升2倍,輔助索引的連接操作性能可以提高5倍。
查看AHI的工作狀態:
show engine innodb status; Hash table size:代表AHI的大小; hash searches/s:代表命中hash查詢的頻率; non-hash searches/s:代表沒有命中hash查詢的頻率;注意:hash查詢是等值查詢,例如模糊查詢、范圍查找,是不能使用hash索引的。用戶可以根據實際場景去權衡是否要開啟AHI。
4.預讀 (Read Ahead)
預讀(read-ahead)操作是一種IO操作,用于異步將磁盤的頁讀取到buffer pool中,預料這些頁會馬上被讀取到。預讀請求的所有頁集中在一個范圍內。InnoDB使用兩種預讀算法:
innodb_read_ahead_threshold 這個參數控制InnoDB在檢測順序頁面訪問模式時的靈敏度。如果在一個區塊順序讀取的頁數大于或者等于 innodb_read_ahead_threshold 這個參數,InnoDB啟動預讀操作來讀取下一個區塊。innodb_read_ahead_threshold參數值的范圍是 0-64,默認值為56. 這個值越高則訪問默認越嚴格。比如,如果設置為48,在當前區塊中當有48個頁被順序訪問時,InnoDB就會啟動異步的預讀操作,如果設置為8,則僅僅有8個頁被順序訪問就會啟動異步預讀操作。你可以在MySQL配置文件中設置這個值,或者通過SET GLOBAL 語句動態修改(需要有set global 權限)。
通過 SHOW INNODB ENGINE STATUS 命令輸出的統計信息可以幫助你評估預讀算法的效果,統計信息包含了下面幾個值:
innodb_buffer_pool_read_ahead 通過預讀異步讀取到buffer pool的頁數 innodb_buffer_pool_read_ahead_evicted 預讀的頁沒被使用就被驅逐出buffer pool的頁數,這個值與上面預讀的頁數的比值可以反應出預讀算法的優劣。 innodb_buffer_pool_read_ahead_rnd 由InnoDB觸發的隨機預讀次數。更多精彩內容,歡迎關注微信公眾號
總結
以上是生活随笔為你收集整理的MySQL之Innodb引擎的4大特性的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: P1085 [NOIP2004 普及组第
- 下一篇: 若依设置匿名访问路径