偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

一文搞懂 MySQL InnoDB架構(gòu) Buffer Pool、Change Buffer、自適應(yīng)哈希索引、Log Buffer

數(shù)據(jù)庫 MySQL
Buffer Pool 是主內(nèi)存中的一個區(qū)域,它在訪問時緩存表和索引數(shù)據(jù)。Buffer Pool 允許頻繁使用的數(shù)據(jù)直接從內(nèi)存中訪問,從而加快處理速度。

InnoDB 架構(gòu)誕生

2003 年 12 月 24 日,平安夜,林淵從維修臺猛然驚醒,耳邊是 DBA 的怒吼:"商品庫又被表鎖卡死了!每秒 500 單變 5 單!"

"小林,數(shù)據(jù)庫鎖表了,MyISAM 的表鎖就是定時炸彈!我們要突破技術(shù)封鎖,開發(fā)一套劃時代的存儲引擎“ CTO 對小林說道。

生在 2025 年作為互聯(lián)網(wǎng)打工牛馬的林淵,學(xué)過很多關(guān)于 MySQL 的技術(shù),記憶如潮水涌入——2025 年的 InnoDB 架構(gòu)圖在他腦中展開,InnoDB 內(nèi)存架構(gòu)、磁盤架構(gòu);

以及那些 Buffer Pool、Change Buffer 的代碼如同梵高星月夜般絢爛,解鎖《InnoDB 設(shè)計圖鑒》,準(zhǔn)備揚(yáng)名立萬。

于是他在京都國際數(shù)據(jù)庫提交一篇提案:《論行級鎖與內(nèi)存緩沖池——下一代存儲引擎設(shè)計提案》,附件性能對比圖震撼業(yè)界。

場景

MyISAM

"InnoDB"原型

100 萬并發(fā)更新

崩潰

TPS 18,492

范圍查詢

12.8s

0.3s

InnoDB 內(nèi)存結(jié)構(gòu)主要包含 Buffer Pool 、Change Buffer 、Adaptive Hash Index (自適應(yīng)哈希索引)和 Log Buffer。

Buffer Pool

Buffer Pool 是主內(nèi)存中的一個區(qū)域,它在訪問時緩存表和索引數(shù)據(jù)。Buffer Pool 允許頻繁使用的數(shù)據(jù)直接從內(nèi)存中訪問,從而加快處理速度。

Buffer Pool 是 InnoDB 引擎的核心內(nèi)存組件,采用預(yù)分配的連續(xù)內(nèi)存空間,默認(rèn)大小通過 innodb_buffer_pool_size 配置(建議設(shè)置為物理內(nèi)存的 60-80%)。

其本質(zhì)是一個基于頁(Page)的緩存系統(tǒng),通過 Page Directory 和 Free List 實現(xiàn)高效內(nèi)存管理。

為了提高大量讀取操作的效率,緩沖池被劃分為可以潛在地包含多行的頁面。

Buffer Pool LRU 算法

Buffer Pool 使用 LRU 算法的變體進(jìn)行管理。當(dāng)需要空間向緩沖池中添加新頁面時,最近最少使用的頁面被移除,并將新頁面添加到列表的中間。

這種中間插入策略將列表視為兩個子列表:

  • 在頭部,一個包含最近訪問的新(“young”)頁面的子列表,稱之為 「New Sublist」
  • 在尾部,一個包含較舊(“Old”)頁面的子列表,稱之為 「Old Sublist」,這些頁面數(shù)據(jù)通常是較少被訪問的。

圖片圖片

算法將頻繁使用的頁面保留在「New Sublist」中。「Old Sublist」包含使用頻率較低的頁面。

默認(rèn)情況下,算法按以下方式運(yùn)行:

  • Buffer Pool 的 3/8 用于「Old Sublist」。
  • 列表的中點(diǎn)是「New Sublist」的尾部與「Old Sublist」的頭部相交的邊界。
  • 當(dāng) InnoDB 將頁面讀入 Buffer Pool 時,它最初將其插入中點(diǎn)(「Old Sublist」的頭部)??梢宰x取頁面,因為它需要用于用戶發(fā)起的操作,如 SQL 查詢,或者作為 InnoDB 自動執(zhí)行的預(yù)讀操作的組成部分。
  • 訪問「Old Sublist」中的頁面數(shù)據(jù)會將其設(shè)置為“Young”,將其移動到「New Sublist」的頭部。如果頁面是因為用戶發(fā)起的操作而讀取的,則第一次訪問立即發(fā)生,頁面變?yōu)椤癥oung”。如果頁面是因為預(yù)讀操作而讀取的,則第一次訪問不會立即發(fā)生。
  • 隨著數(shù)據(jù)庫的運(yùn)行,Buffer Pool 中未被訪問的頁面會通過向列表尾部移動而“老化”?!窷ew Sublist」和「Old Sublist」中的頁面都會隨著其他頁面變?yōu)樾马撁娑匣.?dāng)頁面在中間插入時,「Old Sublist」中的頁面也會老化。最終,一個未被使用的頁面會到達(dá)「Old Sublist」的尾部并被淘汰。

優(yōu)化提示:應(yīng)將緩沖池的大小設(shè)置為盡可能大的值,同時為服務(wù)器上其他進(jìn)程運(yùn)行留出足夠的內(nèi)存,避免過度分頁。緩沖池越大, InnoDB 就越像內(nèi)存數(shù)據(jù)庫,一次從磁盤讀取數(shù)據(jù),然后在后續(xù)讀取中從內(nèi)存中訪問數(shù)據(jù)。

Change Buffer

"每秒 10 萬次非主鍵更新,磁盤 IOPS 爆表!"運(yùn)維總監(jiān)癱坐在監(jiān)控屏前。林淵拔下服務(wù)器電源:"上 Change Buffer!"

實時監(jiān)控屏上,磁盤寫入曲線從鋸齒狀驟變?yōu)槠交本€:

Before: IOPS 15,000 → After: 2,300 (下降85%)

甲骨文特派員 Mike 臉色鐵青:"這算法...至少超越時代十年!”

林淵清了清嗓子,繼續(xù)給大家解釋 Change Buffer 的設(shè)計思路……

Change Buffer 是一種特殊的數(shù)據(jù)結(jié)構(gòu),針對非唯一二級索引的寫優(yōu)化結(jié)構(gòu),用于緩存當(dāng)二級索引頁不在 Buffer Pool 中時的寫操作。

當(dāng)二級索引頁不在緩沖池中時,用于緩存對這些頁面的更改。這些由 INSERT 、 UPDATE 或 DELETE 操作(DML)產(chǎn)生的緩沖更改,將在頁面通過其他讀取操作加載到緩沖池時進(jìn)行合并。

  • 若目標(biāo)頁不在 Buffer Pool,將變更記錄寫入 Change Buffer 生成 Redo Log 保證持久化;
  • 當(dāng)后續(xù)讀取該索引頁時,將 Change Buffer 中的變更合并(Merge)到 Buffer Pool,觸發(fā)異步刷盤。

圖片圖片

臺下有人問:“有了 Buffer Pool 為何還要再設(shè)計一個 Change Buffer 呢?”

與聚簇索引不同,二級索引通常是非唯一的,且對二級索引的插入操作往往以相對隨機(jī)的順序發(fā)生。

同樣,刪除和更新操作也可能影響索引樹中不相鄰的二級索引頁。

當(dāng)其他操作將受影響的頁讀入 Buffer Pool 時,隨后將緩存的更改合并,避免了從磁盤讀取二級索引頁至 Buffer Pool 所需的大量隨機(jī)訪問 I/O。

系統(tǒng)在空閑時段或緩慢關(guān)閉期間運(yùn)行的清除操作會周期性地將更新的索引頁寫入磁盤。

相較于立即逐條寫入磁盤,清除操作能以更高效的方式批量寫入包含連續(xù)索引值的磁盤塊。

Change Buffer 有什么不足呢?

當(dāng)存在大量受影響的行和需要更新的二級索引時,Change Buffer 合并可能需要數(shù)小時。

在此期間,磁盤 I/O 會增加,可能導(dǎo)致磁盤密集型查詢顯著變慢。Change Buffer 合并操作可能在事務(wù)提交后持續(xù)進(jìn)行,甚至在服務(wù)器關(guān)閉并重啟后仍會繼續(xù)。

在內(nèi)存中,Change Buffer 占用 Buffer Pool 的一部分空間。在磁盤上,Change Buffer 屬于系統(tǒng)表空間的一部分,當(dāng)數(shù)據(jù)庫服務(wù)器關(guān)閉時,索引變更將在此處緩沖存儲。

Change Buffer 劃時代意義

當(dāng)對表執(zhí)行 INSERT 、 UPDATE 和 DELETE 操作時,索引列的值(尤其是二級鍵的值)通常處于無序狀態(tài),需要大量 I/O 操作來更新二級索引。

當(dāng)相關(guān)頁面不在 Buffer Pool 中時,Change Buffer 會緩存對二級索引條目的修改,從而避免立即從磁盤讀取頁面所產(chǎn)生的高昂 I/O 開銷。

當(dāng)頁面被加載到 Buffer Pool 時,緩沖的更改會被合并,更新后的頁面隨后會刷寫到磁盤。

由于變更緩沖能夠減少磁盤讀寫次數(shù),因此對于 I/O 密集型工作負(fù)載(例如涉及大量 DML 操作的應(yīng)用場景,如批量插入)具有重要價值,這類場景可顯著受益于 Change Buffer 機(jī)制。

Adaptive Hash Index(自適應(yīng)哈希索引)

2005 年 eBay 中國競標(biāo)現(xiàn)場,林淵與 Oracle 團(tuán)隊正面對決。

"貴司方案處理不了熱點(diǎn)數(shù)據(jù)吧?"Oracle 首席亮出 TPC-C 測試報告。林淵輕笑一聲,敲下:

SET GLOBAL innodb_adaptive_hash_index=ON;
-- 激活哈希索引

瞬間,用戶 ID 查詢從 378ms 降至 0.09ms。

自適應(yīng)哈希索引(Adaptive Hash Index,AHI) 是 InnoDB 存儲引擎內(nèi)部自動創(chuàng)建和管理的哈希索引,用于優(yōu)化 等值查詢(如 WHERE key = 'value' 的性能。

與傳統(tǒng)手動創(chuàng)建的哈希索引不同,AHI 完全由 InnoDB 根據(jù)查詢模式動態(tài)生成和銷毀,無需用戶干預(yù)。

核心作用:通過將頻繁訪問的索引鍵值映射到哈希表,繞過 B+ 樹的逐層查找,直接定位到目標(biāo)數(shù)據(jù)頁,從而減少磁盤 I/O 和 CPU 開銷。

他的觸發(fā)條件是什么?

InnoDB 通過監(jiān)控索引頁的訪問模式,動態(tài)決定是否創(chuàng)建 AHI:

  • 頻率閾值:同一索引頁被連續(xù)訪問超過 100 次。
  • 查詢模式匹配:相同查詢條件多次訪問同一頁(次數(shù)閾值:頁中記錄數(shù) / 16)。

生命周期管理

  • 自動創(chuàng)建:滿足觸發(fā)條件時動態(tài)生成哈希條目。
  • 自動淘汰

當(dāng)索引頁不再被頻繁訪問時,通過 LRU 機(jī)制逐步移除哈希條目。

當(dāng)表被刪除或重建時,相關(guān) AHI 條目自動清理。

工作流程如下圖所示:

圖片圖片

優(yōu)缺點(diǎn)分析

優(yōu)點(diǎn)

局限性

減少等值查詢的 B+ 樹遍歷層級

僅適用于等值查詢(=, IN),不適用范圍查詢

降低 CPU 和 I/O 開銷

哈希沖突可能影響性能

完全自動化,無需人工維護(hù)

高并發(fā)場景可能因鎖爭用成為瓶頸

對熱點(diǎn)數(shù)據(jù)訪問有顯著加速效果

內(nèi)存占用增加(需權(quán)衡 innodb_adaptive_hash_index_parts

使用場景建議

  • 推薦開啟: OLTP 系統(tǒng)中以等值查詢?yōu)橹鞯膱鼍埃ㄈ缬脩糁行?、訂單查詢)?/span>
  • 建議關(guān)閉

寫密集型負(fù)載(如日志寫入)。

內(nèi)存緊張或出現(xiàn)大量哈希沖突時。

使用 SSD 且 Buffer Pool 足夠大時,B+ 樹自身性能已足夠。

Log Buffer(日志緩沖區(qū))

"林工,交易系統(tǒng)每秒百萬事務(wù),如何保證零丟失?"

用 Redo Log 實現(xiàn)!避免每次事務(wù)操作都寫磁盤,我設(shè)計了 Log Buffer。

Log Buffer 是 InnoDB 存儲引擎用于臨時緩存 重做日志(Redo Log) 的內(nèi)存區(qū)域。

Log Buffer 大小由 innodb_log_buffer_size 變量定義,默認(rèn)大小為 64MB。

所有事務(wù)對數(shù)據(jù)的修改在寫入磁盤前,其對應(yīng)的 Redo Log 會先寫入 Log Buffer,隨后按策略批量刷新到磁盤的 Redo Log 文件中。

設(shè)計目標(biāo)

  1. 減少磁盤 I/O 次數(shù):合并多個日志寫入操作,避免頻繁的小數(shù)據(jù)量磁盤寫入。
  2. 提升事務(wù)響應(yīng)速度:延遲日志刷盤,降低事務(wù)提交的等待時間。
  3. 保證持久性(Durability):通過可控的刷盤策略,確保已提交事務(wù)的日志最終持久化。

Log Buffer 內(nèi)容會定期刷新到磁盤。較大的 Log Buffer 允許大型事務(wù)在提交前無需將 Redo Log 數(shù)據(jù)寫入磁盤。

因此,若有更新、插入或刪除大量行的事務(wù),增大 Log Buffer 可節(jié)省磁盤 I/O。

Log Buffer 實現(xiàn)原理

Log Buffer 內(nèi)存結(jié)構(gòu)與寫入流程:

  1. 日志生成
  • 事務(wù)修改數(shù)據(jù)頁時,生成 Redo Log 記錄。
  • 日志記錄包含修改內(nèi)容、LSN(Log Sequence Number)等信息。
  1. 緩沖區(qū)寫入
  • Log Buffer 空間足夠,則日志按順序追加到 Log Buffer 的空閑位置。

  • 使用 buf_free 指針標(biāo)記當(dāng)前寫入偏移量。

  1. 刷盤觸發(fā)條件

  • 事務(wù)提交:根據(jù) innodb_flush_log_at_trx_commit 設(shè)置決定是否刷盤。

  • 緩沖區(qū)滿:當(dāng)寫入數(shù)據(jù)超過緩沖區(qū)空閑空間時強(qiáng)制刷盤。

  • 定時任務(wù):每隔 innodb_flush_log_at_timeout 秒觸發(fā)刷盤(策略為 0 或 2 時)。

圖片圖片

刷盤策略詳解

參數(shù)值

行為描述

數(shù)據(jù)安全性

性能

適用場景

0

日志每秒刷盤一次,事務(wù)提交時不強(qiáng)制刷盤

最低

最高

非關(guān)鍵數(shù)據(jù)批量處理

1

每次事務(wù)提交時同步刷盤(fsync)

最高

最低

金融交易等高安全需求

2

事務(wù)提交時寫入操作系統(tǒng)緩存,不立即刷盤;每秒由操作系統(tǒng)異步刷盤

中等

較高

常規(guī)業(yè)務(wù)系統(tǒng)

Log Buffer 與 Redo Log 協(xié)作

1. 與 Redo Log 文件的關(guān)系

  • 循環(huán)寫入:Redo Log 文件(如 ib_logfile0ib_logfile1)以循環(huán)方式復(fù)用。
  • LSN 協(xié)調(diào)

每個日志記錄攜帶 LSN,全局唯一且遞增。

Checkpoint LSN 標(biāo)記已持久化的日志位置。

2. 崩潰恢復(fù)流程

圖片圖片

  • 重啟時掃描 Redo Log:從最后一個 Checkpoint LSN 開始重放日志。
  • 前滾(Redo):將 Log Buffer 中未刷盤的日志重新應(yīng)用到數(shù)據(jù)頁。
  • 后滾(Undo):通過 Undo Log 回滾未提交的事務(wù)。

3. Group Commit 優(yōu)化

圖片圖片

  • 合并提交:多個事務(wù)的日志寫入合并為一次磁盤操作。
  • 工作流程
  1. 事務(wù)提交時,將日志追加到 Log Buffer。
  2. 由后臺線程統(tǒng)一將多個事務(wù)的日志批量寫入磁盤。
  3. 減少頻繁的 fsync 調(diào)用,提升高并發(fā)下的吞吐量。

Log Buffer 通過內(nèi)存緩沖和批量刷盤機(jī)制,在 事務(wù)持久性 與 系統(tǒng)性能 之間取得平衡。

合理配置 innodb_flush_log_at_trx_commit 和緩沖區(qū)大小,結(jié)合 Group Commit 等優(yōu)化技術(shù),可顯著提升高并發(fā)場景下的數(shù)據(jù)庫性能。

同時,需根據(jù)業(yè)務(wù)容忍度選擇恰當(dāng)?shù)乃⒈P策略,避免數(shù)據(jù)丟失風(fēng)險。


責(zé)任編輯:武曉燕 來源: 碼哥跳動
相關(guān)推薦

2024-10-23 08:47:46

2023-07-31 08:24:34

MySQL索引計數(shù)

2022-03-26 08:49:13

MySQL數(shù)據(jù)存儲

2023-05-03 21:34:34

MySQL狀態(tài)變量

2021-03-04 00:09:31

MySQL體系架構(gòu)

2021-03-01 18:37:15

MySQL存儲數(shù)據(jù)

2019-04-03 09:27:01

MySQLInnoDB務(wù)ACID

2022-03-22 15:05:15

MySQL緩沖池

2025-01-02 11:55:08

HashMapJava哈希沖突

2020-03-18 14:00:47

MySQL分區(qū)數(shù)據(jù)庫

2022-03-30 09:23:15

MySQL緩沖

2024-04-12 12:19:08

語言模型AI

2022-03-24 08:51:48

Redis互聯(lián)網(wǎng)NoSQL

2023-11-21 08:37:09

2022-08-31 08:23:27

SAE日志架構(gòu)

2022-10-12 08:52:00

內(nèi)存緩沖管理

2012-12-06 10:00:48

InnoDBMySQL

2025-05-26 04:00:20

2025-02-20 10:04:35

2023-10-07 15:56:49

三鏈表緩存頁flush鏈表
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號