国产精品久久久aaaa,日日干夜夜操天天插,亚洲乱熟女香蕉一区二区三区少妇,99精品国产高清一区二区三区,国产成人精品一区二区色戒,久久久国产精品成人免费,亚洲精品毛片久久久久,99久久婷婷国产综合精品电影,国产一区二区三区任你鲁

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

關于InnoDB的內存結構及原理詳解

jf_f8pIz0xS ? 來源:SH的全棧筆記 ? 作者:SH的全棧筆記 ? 2021-04-16 16:15 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

之前寫過一篇文章「簡單了解InnoDB原理」,現在回過頭看,其實里面只是把緩沖池(Buffer Pool),重做日志緩沖(Redo Log Buffer)、插入緩沖(Insert Buffer)和自適應哈希索引Adaptive Hash Index)等概念簡單的介紹了一下。

除此之外還聊了一下MySQL和InnoDB的日志,和兩次寫,總的來說算是一個入門級別的介紹,這篇文章就來詳細介紹一下InnoDB的內存結構。

InnoDB內存結構

其大致結構如下圖。

InnoDB內存的兩個主要區域分別為Buffer Pool和Log Buffer,此處的Log Buffer目前是用于緩存Redo Log。而Buffer Pool則是MySQL或者說InnoDB中,十分重要、核心的一部分,位于主存。這也是為什么其訪問數據的效率高,你可以暫時把它理解成Redis那樣的內存數據庫,因為我們更新和新增當然它不是,只是這樣會更加方便我們理解。

Buffer Pool

通常來說,宿主機80%的內存都應該分配給Buffer Pool,因為Buffer Pool越大,其能緩存的數據就更多,更多的操作都會發生在內存,從而達到提升效率的目的。

由于其存儲的數據類型和數據量非常多,Buffer Pool存儲的時候一定會按照某些結構去存儲,并且做了某些處理。否則獲取的時候除了遍歷所有數據之外,沒有其他的捷徑,這樣的低效率操作肯定是無法支撐MySQL的高性能的。

因此,Buffer Pool被分成了很多頁,這在之前的文章中也有講過,這里不再贅述。每頁可以存放很多數據,剛剛也提到了,InnoDB一定是對數據做了某些操作。

InnoDB使用了鏈表來組織頁和頁中存儲的數據,頁與頁之間形成了雙向鏈表,這樣可以方便的從當前頁跳到下一頁,同時使用LRU(Least Recently Used)算法去淘汰那些不經常使用的數據。

同時,每頁中的數據也通過單向鏈表進行鏈接。因為這些數據是分散到Buffer Pool中的,單向鏈表將這些分散的內存給連接了起來。

Log Buffer

Log Buffer用來存儲那些即將被刷入到磁盤文件中的日志,例如Redo Log,該區域也是InnoDB內存的重要組成部分。Log Buffer的默認值為16M,如果我們需要進行調整的話,可以通過配置參數innodb_log_buffer_size來進行調整。

當Log Buffer如果較大,就可以存儲更多的Redo Log,這樣一來在事務提交之前我們就不需要將Redo Log刷入磁盤,只需要丟到Log Buffer中去即可。因此較大的Log Buffer就可以更好的支持較大的事務運行;同理,如果有事務會大量的更新、插入或者刪除行,那么適當的增大Log Buffer的大小,也可以有效的減少部分磁盤I/O操作。

至于Log Buffer中的數據刷入到磁盤的頻率,則可以通過參數innodb_flush_log_at_trx_commit來決定。

Buffer Pool的LRU算法

了解完了InnoDB的內存結構之后,我們來仔細看看Buffer Pool的LRU算法是如何實現將最近沒有使用過的數據給過期的。

原生LRU

首先明確一點,此處的LRU算法和我們傳統的LRU算法有一定的區別。為什么呢?因為實際生產環境中會存在全表掃描的情況,如果數據量較大,可能會將Buffer Pool中存下來的熱點數據給全部替換出去,而這樣就會導致該段時間MySQL性能斷崖式下跌。

對于這種情況,MySQL有一個專用名詞叫緩沖池污染。所以MySQL對LRU算法做了優化。

優化后的LRU

優化之后的鏈表被分成了兩個部分,分別是 New Sublist 和 Old Sublist,其分別占用了 Buffer Pool 的3/4和1/4。

鏈表的前3/4,也就是 New Sublist 存放的是訪問較為頻繁的頁,而后1/4也就是 Old Sublist 則是反問的不那么頻繁的頁。Old Sublist中的數據,會在后續Buffer Pool剩余空間不足、或者有新的頁加入時被移除掉。

了解了鏈表的整體構造和組成之后,我們就以新頁被加入到鏈表為起點,把整體流程走一遍。首先,一個新頁被放入到Buffer Pool之后,會被插入到鏈表中 New Sublist 和 Old Sublist 相交的位置,該位置叫MidPoint。

該鏈表存儲的數據來源有兩部分,分別是:

MySQL的預讀線程預先加載的數據

用戶的操作,例如Query查詢

默認情況下,由用戶操作影響而進入到Buffer Pool中的數據,會被立即放到鏈表的最前端,也就是 New Sublist 的 Head 部分。但如果是MySQL啟動時預加載的數據,則會放入MidPoint中,如果這部分數據被用戶訪問過之后,才會放到鏈表的最前端。

這樣一來,雖然這些頁數據在鏈表中了,但是由于沒有被訪問過,就會被移動到后1/4的 Old Sublist中去,直到被清理掉。

優化Buffer Pool的配置

在實際的生產環境中,我們可以通過變更某些設置,來提升Buffer Pool運行的性能。

例如,我們可以分配盡量多的內存給Buffer Pool,如此就可以緩存更多的數據在內存中

當前有足夠的內存時,就可以搞多個Buffer Pool實例,減少并發操作所帶來的數據競爭

當我們可以預測到即將到來的大量請求時,我們可以手動的執行這部分數據的預讀請求

我們還可以控制Buffer Pool刷數據到磁盤的頻率,以根據當前MySQL的負載動態調整

那我們怎么知道當前運行的 MySQL 中 Buffer Pool 的狀態呢?我們可以通過命令show engine innodb status來查看。這個命令是看 InnoDB 整體的狀態的, Buffer Pool 相關的監控指標包含在了其中,在Buffer Pool And Memory模塊中。

樣例如下。

---------------------- BUFFER POOL AND MEMORY ---------------------- Total large memory allocated 137428992 Dictionary memory allocated 972752 Buffer pool size 8191 Free buffers 4596 Database pages 3585 Old database pages 1303 Modified db pages 0 Pending reads 0 Pending writes: LRU 0, flush list 0, single page 0 Pages made young 1171, not young 0 0.00 youngs/s, 0.00 non-youngs/s Pages read 655, created 7139, written 173255 0.00 reads/s, 0.00 creates/s, 0.00 writes/s No buffer pool page gets since the last printout Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s LRU len: 3585, unzip_LRU len: 0 I/O sum[0]:cur[0], unzip sum[0]:cur[0]

解釋一些關鍵的指標所代表的含義:

Total memory allocated:分配給 Buffer Pool 的總內存

Dictionary memory allocated:分配給 InnoDB 數據字典的總內存

Buffer pool size:分配給 Buffer Pool 中頁的內存大小

Free buffers:分配給 Buffer Pool 中 Free List 的內存大小

Database pages:分配給 LRU 鏈表的內存大小

Old database pages:分配給 LRU 子鏈表的內存大小

Modified db pages:當前Buffer Pook中被更新的頁的數量

Pending reads:當前等待讀入 Buffer Pool 的頁的數量

Pending writes LRU:當前在 LRU 鏈表中等待被刷入磁盤的臟頁數量

都是些很常規的配置項,你可能會比較好奇什么是 Free List。

Free List 中存放的都是未被使用的頁。因為MySQL啟動的時候,InnoDB 會預先申請一部分頁。如果當前頁還未被使用,就會被保存在 Free List 中。

知道了 Free List,那么你也應該知道 Flush List,里面保存的是所有的臟頁,都是被更改后需要刷入到磁盤的。

自適應哈希索引

自適應哈希索引(Adaptive Hash Index)是配合Buffer Pool工作的一個功能。自適應哈希索引使得MySQL的性能更加接近于內存服務器。

如果要啟用自適應哈希索引,可以通過更改配置innodb_adaptive_hash_index來開啟。如果不想啟用,也可以在啟動的時候,通過命令行參數--skip-innodb-adaptive-hash-index來關閉。

自適應哈希索引是根據索引Key的前綴來構建的,InnoDB 有自己的監控索引的機制,當其檢測到為當前某個索引頁建立哈希索引能夠提升效率時,就會創建對應的哈希索引。如果某張表數據量很少,其數據全部都在Buffer Pool中,那么此時自適應哈希索引就會變成我們所熟悉的指針這樣一個角色。

當然,創建、維護自適應哈希索引是會帶來一定的開銷的,但是比起其帶來的性能上的提升,這點開銷可以直接忽略不計。但是,是否要開啟自適應哈希索引還是需要看具體的業務情況的,例如當我們的業務特征是有大量的并發Join查詢,此時訪問自適應哈希索引被產生競爭。并且如果業務還使用了LIKE或者%等通配符,根本就不會用到哈希索引,那么此時自適應哈希索引反而變成了系統的負擔。

所以,為了盡可能的減少并發情況下帶來的競爭,InnoDB對自適應哈希索引進行了分區,每個索引都被綁定到了一個特定的分區,而每個分區都由單獨的鎖進行保護。其實通俗點理解,就是降低了鎖的粒度。分區的數量我們可以通過配置innodb_adaptive_hash_index_parts來改變,其可配置的區間范圍為[8, 512]。

Change Buffer

聊完了 Buffer Pool 中索引相關,剩下的就是 Change Buffer 了。Change Buffer是一塊比較特殊的區域,其作用是用于存儲那些當前不在 Buffer Pool 中的但是又被修改過的二級索引。

用流程來描述一下就是,當我們更新了非聚簇索引(二級索引)的數據時,此時應該是直接將其在Buffer Pool中的對應數據更新了即可,但是不湊巧的是,當前二級索引不在 Buffer Pool 中,此時將其從磁盤拉取到 Buffer Pool 中的話,并不是最優的解,因為該二級索引可能之后根本就不會被用到,那么剛剛昂貴的磁盤I/O操作就白費了。

所以,我們需要這么一個地方,來暫存對這些二級索引所做的改動。當被緩存的二級索引頁被其他的請求加載到了Buffer Pool 中之后,就會將 Change Buffer 中緩存的數據合并到 Buffer Pool 中去。

當然,Change Buffer也不是沒有缺點。當 Change Buffer 中有很多的數據時,全部合并到Buffer Pool可能會花上幾個小時的時間,并且在合并的期間,磁盤的I/O操作會比較頻繁,從而導致部分的CPU資源被占用。

那你可能會問,難道只有被緩存的頁加載到了 Buffer Pool 才會觸發合并操作嗎?那要是它一直沒有被加載進來,Change Buffer 不就被撐爆了?很顯然,InnoDB在設計的時候考慮到了這個點。除了對應的頁加載,提交事務、服務停機、服務重啟都會觸發合并。
編輯:lyn

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 內存
    +關注

    關注

    9

    文章

    3209

    瀏覽量

    76360
  • MySQL
    +關注

    關注

    1

    文章

    905

    瀏覽量

    29518
  • 索引
    +關注

    關注

    0

    文章

    60

    瀏覽量

    10810
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    不同于HBM垂直堆疊,英特爾新型內存ZAM技術采用交錯互連拓撲結構

    不同于HBM垂直堆疊,英特爾新型內存ZAM技術采用交錯互連拓撲結構 ? 據日本媒體PCWatch報道,英特爾在2026年日本英特爾連接大會(Intel Connection Japan 2026)上
    的頭像 發表于 02-11 11:31 ?690次閱讀
    不同于HBM垂直堆疊,英特爾新型<b class='flag-5'>內存</b>ZAM技術采用交錯互連拓撲<b class='flag-5'>結構</b>

    Linux內核伙伴系統內存申請函數詳解:從原理到實戰

    在 Linux 內核中,內存管理是整個系統穩定運行的基石,而伙伴系統(Buddy System) 作為內核物理內存分配的核心機制,更是驅動開發、內核模塊開發的必備知識點。它通過 "2 的冪
    的頭像 發表于 02-10 16:58 ?3630次閱讀
    Linux內核伙伴系統<b class='flag-5'>內存</b>申請函數<b class='flag-5'>詳解</b>:從原理到實戰

    內存條崩了?漲了十倍的內存顆粒賣給誰?內存芯片接下來怎么玩?

    內存
    芯廣場
    發布于 :2026年01月26日 17:48:21

    keil中c語言的動態分配內存

    關于內存的錯誤往往都是毀滅性的。下面我列舉幾點最容易犯的錯誤,希望能幫助到大家。 (1)對空指針(NULL)解引用。看下面的代碼: 這段代碼看上去似乎沒什么錯誤,但存在潛在的風險:由于沒有對指針p
    發表于 01-21 06:04

    內存持續漲價,多重信號預警成本壓力#內存芯片#漲價#行業#消費電子#AI#

    內存芯片
    jf_15747056
    發布于 :2026年01月08日 18:38:35

    rk基于linux/android內存管理

    一、內存分布 ? U-Boot 由前級 Loader 加載到 CONFIG_SYS_TEXT_BASE 地址,初始化時會探明當前系統的總內存容 量, 32 位平臺上認為最大 4GB 可用(但是不影響
    的頭像 發表于 12-15 10:42 ?209次閱讀
    rk基于linux/android<b class='flag-5'>內存</b>管理

    Linux Swap交換空間詳解:Android編譯內存不足?這樣擴充立竿見影

    ? ? 在 ?Linux? 系統使用過程中,你是否遇到過? “ 內存不足 ”? 的報錯?比如編譯? Android? 源碼時,明明按教程操作,卻因物理內存沒達到? 16G? 要求而編譯中斷?這正是
    的頭像 發表于 12-06 08:10 ?4250次閱讀

    PC系列連接器的結構特點與安裝方式詳解

    作為工業連接系統的關鍵組件,PC系列小型圓形電連接器的結構設計直接決定其安裝適配性與運行可靠性。從工程師視角來看,深入理解其結構特點與安裝規范,是確保連接系統穩定運行的前提。電蜂優選基于大量現場應用數據,對該系列的結構特性及安裝
    的頭像 發表于 10-09 15:07 ?1669次閱讀
    PC系列連接器的<b class='flag-5'>結構</b>特點與安裝方式<b class='flag-5'>詳解</b>

    Mysql數據恢復—Windows Server下MySQL(InnoDB)全表誤刪數據恢復案例

    本地服務器,操作系統為windows server。服務器上部署mysql單實例,innodb引擎,獨立表空間。未進行數據庫備份,未開啟binlog。 人為誤操作使用Delete命令刪除數據時未添加where子句,導致全表數據被刪除。刪除后未對該表進行任何操作。需要恢復誤刪除的數據。
    的頭像 發表于 09-23 15:56 ?733次閱讀
    Mysql數據恢復—Windows Server下MySQL(<b class='flag-5'>InnoDB</b>)全表誤刪數據恢復案例

    科普:什么AI 內存技術

    AI 內存是一種專為人工智能 (AI) 應用設計的新型內存技術。與傳統的通用內存(如 DDR5 或 LPDDR5)不同,AI 內存的核心目標是解決 AI 計算中遇到的兩大挑戰:帶寬瓶頸
    的頭像 發表于 09-03 15:44 ?1391次閱讀

    SSH常用命令詳解

    SSH常用命令詳解
    的頭像 發表于 06-04 11:30 ?2008次閱讀

    芯片新關稅涉及的品牌/標簽/產地—詳解

    芯片新關稅涉及的品牌/標簽/產地—詳解
    的頭像 發表于 04-16 17:44 ?1052次閱讀
    芯片新關稅涉及的品牌/標簽/產地—<b class='flag-5'>詳解</b>

    C語言中結構體與聯合體的深度解析:內存布局與應用場景

    一、基礎概念與核心差異 1.1 結構體(Struct)的本質 **結構體是C語言中實現數據封裝的基石,其核心特征在于內存獨立性。每個成員變量在內存中按聲明順序依次排列,形成連續的
    發表于 04-08 09:18

    golang內存分配

    作者:錢文 Go 的分配采用了類似 tcmalloc 的結構.特點: 使用一小塊一小塊的連續內存頁, 進行分配某個范圍大小的內存需求. 比如某個連續 8KB 專門用于分配 17-24 字節,以此減少
    的頭像 發表于 03-31 15:00 ?514次閱讀
    golang<b class='flag-5'>內存</b>分配

    快速搞懂C語言程序內存分區!

    到動態分配的數據等內容。(內存分區圖示)理解這些內存分區的結構和特性,不僅有助于編寫更高效的代碼,還能幫助排查和解決如段錯誤、內存泄漏、棧溢出等常見問題。以下是常見的六
    的頭像 發表于 03-14 17:37 ?1568次閱讀
    快速搞懂C語言程序<b class='flag-5'>內存</b>分區!