溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

InnoDB底層原理是什么

發(fā)布時間:2022-02-19 10:17:10 來源:億速云 閱讀:197 作者:小新 欄目:開發(fā)技術

這篇文章主要為大家展示了“InnoDB底層原理是什么”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“InnoDB底層原理是什么”這篇文章吧。

InnoDB,是MySQL的數據庫引擎之一,現為MySQL的默認存儲引擎,為MySQL AB發(fā)布binary的標準之一。InnoDB由Innobase Oy公司所開發(fā),2006年五月時由甲骨文公司并購。與傳統的ISAM與MyISAM相比,InnoDB的最大特色就是支持了ACID兼容的事務(Transaction)功能,類似于PostgreSQL。

InnoDB底層原理是什么

存儲引擎

很多文章都是直接開始介紹有哪些存儲引擎,并沒有去介紹存儲引擎本身。那么究竟什么是存儲引擎?不知道大家有沒有想過,MySQL是如何存儲我們丟進去的數據的?

其實存儲引擎也很簡單,我認為就是一種存儲解決方案,實現了新增數據、更新數據和建立索引等等功能。

有哪些已有的存儲引擎可以讓我們選擇呢?

InnoDB、MyISAM、Memory、CSV、Archive、Blackhole、Merge、Federated、Example

種類很多,但是常用的存儲引擎目前就只有InnoDB和MyISAM,我也會著重來介紹這兩種存儲引擎。

InnoDB是目前使用最廣的MySQL存儲引擎,MySQL從5.5版本開始InnoDB就已經是默認的存儲引擎了。那你知道為什么InnoDB被廣泛的使用呢?先把這個問題放一放,我們先來了解一下InnoDB存儲引擎的底層原理。

InnoDB的內存架構主要分為三大塊,緩沖池(Buffer Pool)、重做緩沖池(Redo Log Buffer)和額外內存池

緩沖池

InnoDB為了做數據的持久化,會將數據存儲到磁盤上。但是面對大量的請求時,CPU的處理速度和磁盤的IO速度之間差距太大,為了提高整體的效率, InnoDB引入了緩沖池。

當有請求來查詢數據時,如果緩存池中沒有,就會去磁盤中查找,將匹配到的數據放入緩存池中。同樣的,如果有請求來修改數據,MySQL并不會直接去修改磁盤,而是會修改已經在緩沖池的頁中的數據,然后再將數據刷回磁盤,這就是緩沖池的作用,加速讀,加速寫,減少與磁盤的IO交互。

緩沖池說白了就是把磁盤中的數據丟到內存,那既然是內存就會存在沒有內存空間可以分配的情況。所以緩沖池采用了LRU算法,在緩沖池中沒有空閑的頁時,來進行頁的淘汰。但是采用這種算法會帶來一個問題叫做緩沖池污染。

當你在進行批量掃描甚至全表掃描時,可能會將緩沖池中的熱點頁全部替換出去。這樣以來可能會導致MySQL的性能斷崖式下降。所以InnoDB對LRU做了一些優(yōu)化,規(guī)避了這個問題。

MySQL采用日志先行,在真正寫數據之前,會首先記錄一個日志,叫Redo Log,會定期的使用CheckPoint技術將新的Redo Log刷入磁盤,這個后面會講。

除了數據之外,里面還存儲了索引頁、Undo頁、插入緩沖、自適應哈希索引、InnoDB鎖信息和數據字典。下面選幾個比較重要的來簡單聊一聊。

插入緩沖

插入緩沖針對的操作是更新或者插入,我們考慮最壞的情況,那就是需要更新的數據都不在緩沖池中。那么此時會有下面兩種方案。

來一條數據就直接寫入磁盤等數據達到某個閾值(例如50條)才批量的寫入磁盤很明顯,第二種方案要好一點,減少了與磁盤IO的交互。

兩次寫

鑒于都聊到了插入緩沖,我就不得不需要提一嘴兩次寫,因為我認為這兩個InnoDB的特性是相輔相成的。

插入緩沖提高了MySQL的性能,而兩次寫則在此基礎上提高了數據的可靠性。我們知道,當數據還在緩沖池中的時候,當機器宕機了,發(fā)生了寫失效,有Redo Log來進行恢復。但是如果是在從緩沖池中將數據刷回磁盤的時候宕機了呢?

這種情況叫做部分寫失效,此時重做日志就無法解決問題。

InnoDB底層原理是什么
無水干貨:InnoDB底層原理無水干貨:InnoDB底層原理

在刷臟頁時,并不是直接刷入磁盤,而是copy到內存中的Doublewrite Buffer中,然后再拷貝至磁盤共享表空間(你可以就理解為磁盤)中,每次寫入1M,等copy完成后,再將Doublewrite Buffer中的頁寫入磁盤文件。

有了兩次寫機制,即使在刷臟頁時宕機了,在實例恢復的時候也可以從共享表空間中找到Doublewrite Buffer的頁副本,直接將其覆蓋原來的數據頁即可。

自適應哈希索引

自適應索引就跟JVM在運行過程中,會動態(tài)的把某些熱點代碼編譯成Machine Code一樣,InnoDB會監(jiān)控對所有索引的查詢,對熱點訪問的頁建立哈希索引,以此來提升訪問速度。

你可能多次看到了一個關鍵字頁,接下來那我們就來聊一下頁是什么?

頁,是InnoDB中數據管理的最小單位。當我們查詢數據時,其是以頁為單位,將磁盤中的數據加載到緩沖池中的。同理,更新數據也是以頁為單位,將我們對數據的修改刷回磁盤。每頁的默認大小為16k,每頁中包含了若干行的數據,頁的結構如下圖所示。

InnoDB底層原理是什么
無水干貨:InnoDB底層原理無水干貨:InnoDB底層原理

不用太糾結每個區(qū)是干嘛的,我們只需要知道這樣設計的好處在哪兒。每一頁的數據,可以通過FileHeader中的上一下和下一頁的數據,頁與頁之間可以形成雙向鏈表。因為在實際的物理存儲上,數據并不是連續(xù)存儲的。你可以把他理解成G1的Region在內存中的分布。

而一頁中所包含的行數據,行與行之間則形成了單向鏈表。我們存入的行數據最終會到User Records中,當然最初User Records并不占據任何存儲空間。隨著我們存入的數據越來越多,User Records會越來越大,Free Space的空間會越來越小,直到被占用完,就會申請新的數據頁。

User Records中的數據,是按照主鍵id來進行排序的,當我們按照主鍵來進行查找時,會沿著這個單向鏈表一直往后找,

重做日志緩沖

上面聊過,InnoDB中緩沖池中的頁數據更新會先于磁盤數據更新的,InnoDB也會采用日志先行(Write Ahead Log)策略來刷新數據,什么意思呢?當事務開始時,會先記錄Redo Log到Redo Log Buffer中,然后再更新緩沖池頁數據。

Redo Log Buffer中的數據會按照一定的頻率寫到重做日志中去。被更改過的頁就會被標記成臟頁,InnoDB會根據CheckPoint機制來將臟頁刷到磁盤。

日志

上面提到了Redo log,這一小節(jié)就專門來講一講日志,日志分為如下兩個維度。

MySQL層面

InnoDB層面

MySQL日志

MySQL的日志可以分為錯誤日志、二進制文件、查詢日志和滿查詢日志。

錯誤日志 很好理解,就是服務運行過程中發(fā)生的嚴重錯誤日志。當我們的數據庫無法啟動時,就可以來這里看看具體不能啟動的原因是什么二進制文件 它有另外一個名字你應該熟悉,叫Binlog,其記錄了對數據庫所有的更改。查詢日志 記錄了來自客戶端的所有語句慢查詢日志 這里記錄了所有響應時間超過閾值的SQL語句,這個閾值我們可以自己設置,參數為long_query_time,其默認值為10s,且默認是關閉的狀態(tài),需要手動的打開。

InnoDB日志

InnoDB日志就只有兩種,Redo Log和Undo Log,

Redo Log 重做日志,用于記錄事務操作的變化,且記錄的是修改之后的值。不管事務是否提交都會記錄下來。例如在更新數據時,會先將更新的記錄寫到Redo Log中,再更新緩存中頁中的數據。然后按照設置的更新策略,將內存中的數據刷回磁盤。Undo Log 記錄的是記錄的事務開始之前的一個版本,可用于事務失敗之后發(fā)生的回滾。Redo Log記錄的是具體某個數據頁上的修改,只能在當前Server使用,而Binlog可以理解為可以給其他類型的存儲引擎使用。這也是Binlog的一個重要作用,那就是主從復制,另外一個作用是數據恢復。

上面提到過,Binlog中記錄了所有對數據庫的修改,其記錄日志有三種格式。分別是Statement、Row和MixedLevel。

Statement 記錄所有會修改數據的SQL,其只會記錄SQL,并不需要記錄下這個SQL影響的所有行,減少了日志量,提高了性能。但是由于只是記錄執(zhí)行語句,不能保證在Slave節(jié)點上能夠正確執(zhí)行,所以還需要額外的記錄一些上下文信息Row 只保存被修改的記錄,與Statement只記錄執(zhí)行SQL來比較,Row會產生大量的日志。但是Row不用記錄上下文信息了,只需要關注被改成啥樣就行。MixedLevel 就是Statement和Row混合使用。具體使用哪種日志,需要根據實際情況來決定。例如一條UPDATE語句更新了很多的數據,采用Statement會更加節(jié)省空間,但是相對的,Row會更加的可靠。

InnoDB和MyISAM的區(qū)別

由于MyISAM并不常用,我也不打算去深究其底層的一些原理和實現。我們在這里簡單的對比一下這兩個存儲引擎的區(qū)別就好。我們分點來一點點描述。

事務 InnoDB支持事務、回滾、事務安全和奔潰恢復。而MyISAM不支持,但查詢的速度要比InnoDB更快主鍵 InnoDB規(guī)定,如果沒有設置主鍵,就自動的生成一個6字節(jié)的主鍵,而MyISAM允許沒有任何索引和主鍵的存在,索引就是行的地址外鍵 InnoDB支持外鍵,而MyISAM不支持表鎖 InnoDB支持行鎖和表鎖,而MyISAM只支持表鎖全文索引 InnoDB不支持全文索引,但是可以用插件來實現相應的功能,而MyISAM是本身就支持全本索引行數 InnoDB獲取行數時,需要掃全表。而MyISAM保存了當前表的總行數,直接讀取即可。所以,簡單總結一下,MyISAM只適用于查詢大于更新的場景,如果你的系統查詢的情況占絕大多數(例如報表系統)就可以使用MyISAM來存儲,除此之外,都建議使用InnoDB。

以上是“InnoDB底層原理是什么”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業(yè)資訊頻道!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI