您好,登錄后才能下訂單哦!
本篇內容主要講解“MySQL存儲引擎之InnoDB架構的知識點有哪些”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“MySQL存儲引擎之InnoDB架構的知識點有哪些”吧!
進入MySQL的數據庫查看存儲引擎就可以看到MySQL數據庫所有支持的存儲引擎:
登錄后復制SHOW ENGINES
目前有一個引擎Federated不支持,我們只需要清楚其他八種數據庫存儲就好。
MySQL中常見的數據庫引擎有MyISAM、InnoDB、Memory。那么我們就先清楚這三種引擎。
InnoDB是MySQL的默認引擎,一個支持事務安全的存儲引擎。mysql中數據是存儲在物理磁盤上的,而真正的數據處理又是在內存中執行的。由于磁盤的讀寫速度非常慢,如果每次操作都對磁盤進行頻繁讀寫的話,那么性能就會非常差。
為了上述問題,InnoDB將數據劃分為若干頁,以頁作為磁盤與內存交互的基本單位,一般頁的大小為16KB。這樣的話,一次性至少讀取1頁數據到內存中或者將1頁數據寫入磁盤。通過減少內存與磁盤的交互次數,從而提升性能。
這本質上就是一種典型的緩存設計思想,一般緩存的設計基本都是從時間維度或者空間維度進行考量的:
時間維度:如果一條數據正在在被使用,那么在接下來一段時間內大概率還會再被使用。可以認為熱點數據緩存都屬于這種思路的實現。
空間維度:如果一條數據正在在被使用,那么存儲在它附近的數據大概率也會很快被使用。InnoDB的數據頁和操作系統的頁緩存則是這種思路的體現。
下面是官方的InnoDB引擎結構圖,主要分為內存結構和磁盤結構兩大部分。
內存結構主要包括Buffer Pool、Change Buffer、Adaptive Hash Index和Log Buffer四大組件。
Buffer Pool由包含數據、索引、insert buffer ,adaptive hash index,lock 信息及數據字典。緩沖池,簡稱BP。BP以Page頁為單位,默認大小16K,BP的底層采用鏈表數據結構管理Page。在InnoDB訪問表記錄和索引時會在Page頁中緩存,以后使用可以減少磁盤IO操作,提升效率。
緩沖池簡單來說就是一塊內存區域,通過內存的速度來彌補磁盤速度較慢對數據庫性能的影響。在數據庫中進行讀取頁的操作,首先將從磁盤讀到的頁存放在緩沖池中,這個過程稱為將頁"FIX"在緩沖池中。下一次再讀取相同的頁時,首先判斷該頁是否在緩沖池中。若在緩沖池中,稱該頁在緩沖池中被命中。直接讀取該頁。否則讀取磁盤上的頁。對于數據庫中頁的修改操作,則首先修改在緩沖池中的頁,然后再以一定的頻率刷新到磁盤上。這里需要注意的是,頁從緩沖池刷新回磁盤的操作并不是每次頁發生更新時觸發,而是通過一種稱為Checkpoint的機制刷新回磁盤。同樣這也是為了提高數據庫的整體性能。
傳統LUR算法
緩沖池是通過LRU(Latest Recent Used,最近最少使用)算法來進行管理的,即最頻繁使用的頁在LRU列表的最前段,而最少使用的頁在LRU列表的尾端,當緩沖池不能存放新讀取到的頁時,首先釋放LRU列表尾端的頁:
(1)頁已經在緩沖池里,那就只做“移至”LRU頭部的動作,而沒有頁被淘汰;
(2)頁不在緩沖池里,除了做“放入”LRU頭部的動作,還要做“淘汰”LRU尾部頁的動作;
但是InnoDB的LUR算法并不是傳統的LUR算法。
這里有兩個問題:
(1)預讀失效;
(2)緩沖池污染;
我們先了解什么是預讀;
預讀
磁盤讀寫,并不是按需讀取,而是按頁讀取,一次至少讀一頁數據(一般是4K),如果未來要讀取的數據就在頁中,就能夠省去后續的磁盤IO,提高效率。數據訪問,通常都遵循“集中讀寫”的原則,使用一些數據,大概率會使用附近的數據,這就是所謂的“局部性原理”,它表明提前加載是有效的,確實能夠減少磁盤IO。
預讀失效
由于預讀(Read-Ahead),提前把頁放入了緩沖池,但最終MySQL并沒有從頁中讀取數據,稱為預讀失效。
要優化預讀失效,思路是:
(1)讓預讀失敗的頁,停留在緩沖池LRU里的時間盡可能短;
(2)讓真正被讀取的頁,才挪到緩沖池LRU的頭部;
以保證,真正被讀取的熱數據留在緩沖池里的時間盡可能長。
具體方法是:
(1)將LRU分為兩個部分:
新生代(new sublist)
老生代(old sublist)
(2)新老生代收尾相連,即:新生代的尾(tail)連接著老生代的頭(head);
(3)新頁(例如被預讀的頁)加入緩沖池時,只加入到老生代頭部:
如果數據真正被讀取(預讀成功),才會加入到新生代的頭部
如果數據沒有被讀取,則會比新生代里的“熱數據頁”更早被淘汰出緩沖池
新老生代改進版LRU仍然解決不了緩沖池污染的問題。
Log Buffer用來緩存重做日志。
InnoDB有兩個非常重要的日志:undo log、redo log
(1)通過undo log可以看到數據較早版本,實現MVCC,或回滾事務等功能。
(2)通過redo log用來保證事務持久性。
redo日志緩沖區是內存存儲區域,用于保存要寫入磁盤上的日志文件的數據。日志緩沖區大小由innodb_log_buffer_size 變量定義,默認大小為16MB。
日志緩沖區的內容定期刷新到磁盤。較大的日志緩沖區可以運行大型事務,而無需在事務提交之前將重做日志數據寫入磁盤。因此,如果有更新,插入或刪除許多行的事務,則增加日志緩沖區的大小可以節省磁盤I/O。
innodb_flush_log_at_trx_commit :控制如何將日志緩沖區的內容寫入并刷新到磁盤。
innodb_flush_log_at_timeout :控制日志刷新頻率。
如果磁盤I/O導致性能問題,則需要觀察事務,例如涉及許多BLOB條目的事務。只要InnoDB日志緩沖區已滿,便會將其刷新到磁盤,因此增加緩沖區大小可以減少I/O。
日志文件的缺省數量為兩個: ib_logfile0 和 ib_logfile1 。
日志具有固定大小,默認大小取決于MySQL版本。
Adaptive Hash Index自適應hash索引是一種鍵值對的存儲結構,存儲的是熱點頁所在的記錄。InnoDB存儲引擎會自動根據訪問的頻率和模式 來為某些頁建立哈希索引。
上面的圖就是區分B+樹索引和自適應hash索引的區別。 通過參數innodb_adaptive_hash_index來禁用或啟動此特性,默認為開啟。
Change Buffer:MySQL中數據分為內存和磁盤兩個部分;在buffer pool中緩存熱的數據頁和索引頁,減少磁盤讀;通過change buffer就是為了緩解磁盤寫的一種手段。
當需要更新一個數據頁時,如果數據頁在內存中就直接更新。如果數據頁不在內存中。在不影響數據一致性的前下,InooDB 會將這些更新操作緩存在 change buffer 中,這樣就不需要從磁盤中讀入這個數據頁了。在下次查詢需要訪問這個數據頁的時候,將數據頁讀入內存,然后執行 change buffer 中與這個頁有關的操作。通過這種方式就能保證這個數據邏輯的正確性。
雖然名字叫作 change buffer,實際上它是可以持久化的數據。也就是說,change buffer 在內存中有拷貝,也會被寫入到磁盤上(ibdata)。
?將 change buffer 中的操作合并到原數據頁,得到最新結果的過程稱為 merge。以下情況會觸發merge:
訪問這個數據頁;
后臺master線程會定期 merge;
數據庫緩沖池不夠用時;
數據庫正常關閉時;
redo log寫滿時;
change buffer就是在非唯一普通索引頁不在buffer pool中時,對頁進行了寫操作的情況下,先將記錄變更緩沖,等未來數據被讀取時,再將 change buffer 中的操作merge到原數據頁的技術。在MySQL5.5之前,叫插入緩沖(insert buffer),只針對insert做了優化;現在對delete和update也有效,叫做寫緩沖(change buffer)。
到此,相信大家對“MySQL存儲引擎之InnoDB架構的知識點有哪些”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。