Java-85 深入淺出 MySQL InnoDB 存儲結構:Buffer Pool、寫緩沖與日志機制全解

點一下關注吧!!!非常感謝!!持續更新!!!

🚀 AI篇持續更新中!(長期更新)

AI煉丹日志-30-新發布【1T 萬億】參數量大模型!Kimi?K2開源大模型解讀與實踐,持續打造實用AI工具指南!📐🤖

💻 Java篇正式開啟!(300篇)

目前2025年07月28日更新到:
Java-83 深入淺出 MySQL 連接、線程、查詢緩存與優化器詳解
MyBatis 已完結,Spring 已完結,Nginx已完結,Tomcat已完結,分布式服務正在更新!深入淺出助你打牢基礎!

📊 大數據板塊已完成多項干貨更新(300篇):

包括 Hadoop、Hive、Kafka、Flink、ClickHouse、Elasticsearch 等二十余項核心組件,覆蓋離線+實時數倉全棧!
大數據-278 Spark MLib - 基礎介紹 機器學習算法 梯度提升樹 GBDT案例 詳解

請添加圖片描述

InnoDB存儲結構

在 MySQL 5.5 版本開始之后,默認使用 InnoDB 存儲引擎,它擅長處理事務,具有自動奔潰恢復的特性,在日常開發中使用非常廣泛。
下面是 InnoDB 引擎架構圖,主要分為內存結構和磁盤結構兩大部分。

在這里插入圖片描述

內存結構

內存結構主要包括 Buffer Pool、Change Buffer、Adaptive Hash Index 和 Log Buffer 四大組件。

Buffer Pool(緩沖池)

基本概念

緩沖池(Buffer Pool,簡稱BP)是InnoDB存儲引擎的核心內存區域,主要用于緩存表數據和索引數據,以減少磁盤I/O操作,顯著提升數據庫性能。

存儲單元
  • Page(頁):BP的基本管理單位
    • 默認大小:16KB(可通過innodb_page_size參數配置)
    • 包含類型:數據頁、索引頁、undo頁、插入緩沖頁等
    • 每個Page都有對應的控制信息(約5%額外空間)
數據結構

采用改進的鏈表結構管理:

  1. Free List:維護所有空閑頁
  2. LRU List:管理已使用的頁,采用改進的LRU算法
    • 分為young sublist(5/8)和old sublist(3/8)
    • 新頁插入到old sublist中部
    • 頁被訪問時可能移至young區
  3. Flush List:記錄被修改過的臟頁(按LSN排序)
工作流程示例
  1. 當查詢需要讀取某頁數據時:

    • 先在BP中查找(哈希表快速定位)
    • 命中則直接使用內存數據(邏輯讀)
    • 未命中則從磁盤加載(物理讀)
  2. 寫操作流程:

    數據修改
    寫入BP中的頁
    標記為臟頁
    后臺線程定期刷盤
關鍵配置參數
  • innodb_buffer_pool_size:總大小(建議設為物理內存的50-70%)
  • innodb_buffer_pool_instances:實例數(減少鎖爭用)
  • innodb_old_blocks_time:頁轉入young區前的保護期
性能影響
  • 命中率計算公式:
    Hit Ratio = 1 - (innodb_buffer_pool_reads / innodb_buffer_pool_read_requests)
    
  • 良好實踐:監控命中率(建議保持在95%以上),通過預熱腳本提升初始性能
應用場景
  1. 熱點數據訪問:頻繁訪問的數據會長期駐留BP
  2. 事務處理:修改數據先在BP中完成,再異步刷盤
  3. 全表掃描:通過innodb_old_blocks_time避免擠出熱點數據
Page 管理機制詳細說明

● free page(空閑頁):

  • 完全未被使用的頁,處于待分配狀態
  • 不包含任何有效數據
  • 當需要新頁面時,首先從這里分配
  • 示例:當有新數據插入且緩沖區中沒有可用空間時,會從free list獲取free page

● clean page(干凈頁):

  • 已被使用的頁,但數據與磁盤一致
  • 數據未被修改過
  • 可以直接替換而不需要寫回磁盤
  • 示例:執行SELECT操作讀取的數據頁,在未被修改前都是clean page

● dirty page(臟頁):

  • 已被使用且被修改過的頁
  • 內存中的數據與磁盤不一致
  • 需要被刷寫到磁盤才能釋放
  • 示例:執行UPDATE操作修改數據后,對應的數據頁就變成dirty page
鏈表管理機制詳細說明

● free list(空閑鏈表):

  • 維護所有可分配的空閑頁
  • 采用簡單的鏈表結構管理
  • 當需要新頁時,從這里快速獲取
  • 應用場景:新查詢需要加載數據頁時

● flush list(刷新鏈表):

  • 維護所有需要刷盤的臟頁
  • 按照頁面的第一次修改時間排序(oldest_modification)
  • 采用WAL機制,確保事務持久性
  • 與LRU list獨立運作
  • 刷盤策略:后臺線程定期檢查,在系統負載低時批量寫入

● lru list(最近最少使用鏈表):

  • 采用改進的LRU算法管理
  • 結構劃分:
    • new sublist(新子列表,占5/8):
      • 存放熱點數據
      • 新訪問的頁先加入這里
    • old sublist(老子列表,占3/8):
      • 存放較冷數據
      • 新頁默認先加入這里
  • 頁面移動規則:
    1. 新訪問的頁先插入到old sublist頭部
    2. 再次被訪問時,移動到new sublist頭部
    3. 長時間未被訪問的頁會逐漸向尾部移動
    4. 當需要空間時,優先淘汰old sublist尾部的頁
  • 冷數據保護機制:
    • 設置innodb_old_blocks_time參數
    • 防止全表掃描污染緩沖區
改進型LRU算法(LRU with midpoint insertion)

● 普通LRU(Least Recently Used)算法:

  • 采用簡單的末尾淘汰法,使用雙向鏈表結構管理緩存頁
  • 新數據總是從鏈表頭部插入,成為最新的數據
  • 當需要釋放空間時,從鏈表末尾淘汰最久未被訪問的數據
  • 示例:一個包含A->B->C的LRU鏈表,訪問B后會變成B->A->C

● 改進型LRU算法(MySQL InnoDB實現):

  • 將LRU鏈表劃分為兩個區域:
    • new子鏈表(占5/8):存儲熱點數據
    • old子鏈表(占3/8):存儲潛在淘汰數據
  • 關鍵改進點:
    1. 新元素插入位置:不是直接插入鏈表頭部,而是從中間位置(midpoint,即new和old的交界處)插入
    2. 動態調整機制:
      • 如果數據很快被再次訪問(首次訪問后的1秒內),該page會向new子鏈表頭部移動
      • 未被訪問的數據會逐步向old子鏈表尾部移動
    3. 淘汰策略:優先從old子鏈表尾部淘汰頁面

具體工作流程:

  1. 數據讀取階段:

    • 當需要將新Page數據加載到Buffer Pool時
    • InnoDB引擎首先檢查free list是否有可用空閑頁
  2. 內存分配判斷:

    • 情況1:存在足夠空閑頁
      • 從free list移除對應的free page
      • 將該page放入LRU鏈表的midpoint位置(即old子鏈表頭部)
      • 設置首次訪問時間戳
    • 情況2:無足夠空閑頁
      • 觸發LRU淘汰機制:
        1. 從LRU鏈表old子表尾部選擇待淘汰頁
        2. 如果該頁是臟頁,先寫入磁盤
        3. 釋放該頁內存空間
        4. 將新page插入到midpoint位置
  3. 訪問優化:

    • 對于已在LRU鏈表中的page:
      • 若在首次訪問后1秒內再次被訪問:
        • 將其移至new子鏈表頭部
      • 否則保持原位或向old子鏈表尾部移動

應用場景優勢:

  • 有效防止全表掃描等批量操作污染熱點數據
  • 更平滑的熱點數據遷移過程
  • 示例:一個包含1000個page的Buffer Pool,625個page屬于new區域,375個page屬于old區域,新插入的page會先放在第626的位置

Buffer Pool 配置參數:
● show variables like ‘%innodb_page_size%’ 查看page頁大小
● show variables like ‘%innodb_old%’ 查看 LRU list 中 old列表參數
● show variables like ‘%innodb_buffer%’ 查看 Buffer Pool 參數

在這里插入圖片描述

Change Buffer

寫緩沖區(Change Buffer,簡稱CB)是InnoDB存儲引擎中一種優化非唯一普通索引更新的重要機制。在進行DML(INSERT/UPDATE/DELETE)操作時,如果目標數據頁不在緩沖池(Buffer Pool)中,InnoDB不會立即從磁盤加載該頁,而是先將這些變更記錄在Change Buffer中。待未來該數據頁被讀取時,再將Change Buffer中的變更合并到緩沖池中。

核心特性:
  1. 空間占用

    • Change Buffer占用Buffer Pool的空間,默認配置為25%(通過參數innodb_change_buffer_max_size控制)
    • 最大可配置為50%,建議根據業務讀寫比例調整:
      • 寫密集型業務可適當調高
      • 讀密集型業務建議降低配置
  2. 工作流程對比

    • 記錄存在Buffer Pool

      1. 直接修改緩沖池中的頁
      2. 僅需一次內存操作
      -- 示例:當執行UPDATE時,若數據頁已在內存
      UPDATE users SET name='張三' WHERE id=1; -- 內存直接修改
      
    • 記錄不存在Buffer Pool

      1. 將變更寫入Change Buffer
      2. 避免立即的磁盤IO
      3. 后續讀取時合并變更
      -- 示例:首次更新非活躍數據
      UPDATE order_history SET status=2 WHERE order_id=10086; -- 寫入ChangeBuffer
      
  3. 合并觸發時機

    • 主動讀取:當執行SELECT查詢需要加載該數據頁時
    • 后臺線程:由master線程定期合并
    • 空間不足:當Change Buffer空間達到閾值時
適用限制:

僅適用于非唯一普通索引頁,主要原因如下:

  1. 唯一性約束驗證

    • 唯一索引(包括主鍵)必須保證數據唯一性
    • 每次修改必須檢查磁盤現有數據
    • 例如:
      ALTER TABLE products ADD UNIQUE INDEX idx_sku(sku);
      -- 以下操作必須立即校驗唯一性
      INSERT INTO products(sku) VALUES('A1001');
      
  2. 強制磁盤加載

    • 校驗過程會觸發磁盤讀取
    • 數據頁會被加載到Buffer Pool
    • 后續修改直接在緩沖池完成
  3. 典型應用場景

    • 日志表的時間戳索引
    • 訂單歷史表的非關鍵字段索引
    • 批量導入時的輔助索引更新
監控建議:

通過以下命令查看Change Buffer狀態:

SHOW ENGINE INNODB STATUS\G
-- 重點關注:
-- INSERT BUFFER AND ADAPTIVE HASH INDEX
-- merged operations: insert/delete mark/purge

注:在SSD存儲環境下,因隨機IO性能提升,Change Buffer的收益會相對降低,此時可適當減小其配置比例。

Adaptive Hash Index

自適應哈希索引,用于優化對 BP 數據的查詢,InnoDB 存儲引擎會在監控對表索引的查找,如果觀察到建立哈希索引可以帶來速度的提升,則建立哈希索引,所以稱之為自適應。
InnoDB 存儲引擎會自動根據訪問的頻率和模式來為某些頁面建立哈希索引。

Log Buffer(日志緩沖區)

日志緩沖區是數據庫系統中一個重要的內存區域,主要用于臨時存儲即將寫入磁盤日志文件(包括Redo日志和Undo日志)的數據。這個緩沖區作為磁盤I/O操作的緩沖層,可以顯著提高數據庫的寫入性能。

主要功能和工作原理
  1. 數據緩沖:所有DML操作(如INSERT、UPDATE、DELETE)產生的Redo和Undo日志都會先寫入Log Buffer,而不是直接寫入磁盤。Redo日志記錄數據頁的物理變化,用于崩潰恢復;Undo日志記錄事務前的數據狀態,用于事務回滾。

  2. 自動刷新機制

    • 當緩沖區空間寫滿時(達到innodb_log_buffer_size設置的大小),系統會自動將緩沖區內容刷新到磁盤的日志文件中。
    • 對于大事務(如涉及BLOB或多行更新的操作),增大日志緩沖區可以減少磁盤I/O次數,提高性能。
  3. 手動刷新控制:通過innodb_flush_log_at_trx_commit參數可以配置不同的日志刷新策略:

    • 0:每隔1秒執行一次日志寫入和刷盤操作(將LogBuffer內容寫入OS Cache,然后從OS Cache刷到磁盤文件)。這種模式性能最好,但可能在系統崩潰時丟失最多1秒的數據。
    • 1(默認值):每次事務提交時立即執行日志寫入和刷盤操作。這種模式最安全,不會丟失數據,但會產生頻繁的I/O操作,影響性能。
    • 2:每次事務提交時立即將日志寫入OS Cache,但每隔1秒才執行一次刷盤操作。這種模式在系統崩潰時可能會丟失1秒數據,但相比模式1有更好的性能。
實際應用場景
  • 高并發事務系統:對于需要處理大量短事務的系統,適當增大innodb_log_buffer_size(如設置為8MB或16MB)可以減少磁盤I/O壓力。
  • 批量數據處理:在執行大批量數據導入或更新時,可以臨時將innodb_flush_log_at_trx_commit設為0或2,完成后恢復為1。
  • 關鍵業務系統:對數據安全性要求高的系統應保持默認設置(innodb_flush_log_at_trx_commit=1),確保每次事務提交后數據立即持久化。
性能優化建議
  • 監控日志緩沖區使用情況,如果經常出現等待日志緩沖區空間的情況,應考慮增大緩沖區大小。
  • 在SSD存儲環境中,可以適當降低日志刷新頻率,因為SSD的隨機寫入性能較好。
  • 對于主從復制環境,從庫可以配置為較寬松的日志刷新策略以提高復制性能。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/91171.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/91171.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/91171.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux救援模式之應用篇

掛載并訪問文件系統1. 首先識別分區 fdisk -l # 查看所有磁盤和分區 lsblk # 以樹狀結構查看塊設備 blkid # 查看分區的UUID和文件系統類型2. 創建掛載點并掛載分區 mkdir /mnt/rescue # 創建掛載點# 掛載根分區(根據你實際的根分區設備) mount /dev/…

【學習路線】游戲開發大師之路:從編程基礎到獨立游戲制作

前言 游戲開發是一個充滿創意和技術挑戰的領域,它融合了編程、美術、音效、設計等多個學科。隨著游戲產業的蓬勃發展,游戲開發已成為最具吸引力的技術職業之一。本文將為您提供一條從零基礎到游戲開發大師的完整學習路線,涵蓋編程基礎、游戲引…

宇樹 G1 部署(九)——遙操作控制腳本 teleop_hand_and_arm.py 分析與測試部署

首先,我使用的是 v1.0 版本,宇樹最近發力了更新的很快:xr_teleoperate-1.0 teleop_hand_and_arm.py 支持通過 XR 設備(比如手勢或手柄)來控制實際機器人動作,也支持在虛擬仿真中運行。可以根據需要&#x…

第十一天:不定方程求解

每日一道C題:不定方程求解 問題:給定正整數a,b,c。求不定方程 axbyc 關于未知數x和y的所有非負整數解組數。 要求:輸入一行,包含三個正整數a,b,c,兩個整數之間用單個空格…

ElasticStack技術棧概述及Elasticsearch8.2.2集群部署并更換JDK版本為openjdk-17

ElasticStack 一、引言 在當今數據驅動的時代,如何高效地收集、處理和分析日志及其他類型的數據,已成為企業構建可觀測性和運維能力的重要課題。Elastic Stack(早期稱為 ELK Stack)是一套由 Elastic 公司推出的開源技術棧&#xf…

Doris中文檢索效果調優

一、問題描述 原來的日志系統使用的是ES作為底層存儲,后來因為數據量大了之后,出現了寫入存在阻塞和查詢效率變低的問題。后來決定切換到Doris數據庫。 Doris的優勢根據公開資料來看,它在寫入性能、查詢效率和存儲成本上,都優于…

CDN怎么加速跟防御網站攻擊呢?

**CDN(內容分發網絡)**通過分布式架構和智能路由技術,不僅可以加速網站內容訪問,還能有效防御多種網絡攻擊(如DDoS、SQL注入等)。以下是 CDN 如何實現加速和防御的詳細解析:1. CDN 如何加速網站…

【Linux】批量處理多個用戶的 sudo 權限問題

要批量處理多個用戶的 sudo 權限問題,有以下幾種高效方法: 方法一:通過用戶組批量授權(推薦) 這是最安全便捷的方式,只需將用戶加入已有 sudo 權限組(如 wheel 或 sudo):…

云原生MySQL Operator開發實戰(五):擴展與生態系統集成

引言 在前四篇文章中,我們構建了一個功能完備的MySQL Operator,涵蓋了從基礎架構到生產部署的全過程。本文將作為本系列的收官之作,重點探討Operator的擴展能力和與云原生生態系統的深度集成,包括自定義插件系統、與CI/CD流水線的集成、服務網格支持以及與云服務的無縫對接…

【MySQL】數據庫的簡單介紹

1.數據庫是什么簡單來說,數據庫是用于存儲數據和管理數據的軟件。數據庫可以提供遠程服務,通過遠程連接來使用數據庫,因此數據庫也被稱為數據庫服務器!2.為什么要使用數據庫存儲數據用文件就可以了,為什么還要弄一個數…

uniapp,uview icon加載太慢了,老是顯示叉叉,將遠程加載改到本地加載。

處理方式:將遠程字體文件下載到本地進行加載。app.vue。font-face {font-family: uicon-iconfont;src: url(./static/fonts/font_2225171_8kdcwk4po24.ttf) format(truetype);font-weight: normal;font-style: normal;}下載文件:從node_modules找文件u-i…

Python爬蟲01_Requests第一血獲取響應數據

引入requests包,發起請求并獲取響應數據。 import requestsif __name__ "__main__":#step 1:指定urlurl http://www.7k7k.com/#step 2:發起請求,get方法會返回一個響應對象response requests.get(url)#step 3&#x…

Linux定時器和時間管理源碼相關總結

基礎可參考: Linux內核定時器相關內容總結-CSDN博客 定時器來源 定時器也是來源于芯片的硬件定時器,屬于內部外設,有些可能也會用外部定時器,不管咋樣,都屬于芯片外設,既然是外設,那么我們也要編…

JDK17 新特性跟學梳理

JDK17 新特性跟學梳理JDK17 背景介紹一、JDK 17對Switch語句的增強二、字符串拼接三、強制轉換四、密封類Sealed Classes五、Record類六、優化空指針異常信息七、ZGC垃圾收集器八、JVM常量API九、重寫Socket底層API十、JDK飛行記錄事件流十一、EdDSA簽名算法十二、隱藏類十三、…

ESP8266 AT 固件

ESP-12E 是一種常見的 ESP8266 模塊,通常帶有 4MB(32Mbit)閃存,非常適合刷寫 最新版 AT 固件。 ? 適用于 ESP?12E 的 AT 固件推薦 固件來源固件版本特點Espressif 官方v2.2.1.0 (ESP8266 IDF AT)官方最新版,基于 RT…

Node.js(三)之Express

Express 目錄 Express 九、初識Express 9.1 Express簡介 1. 什么是 Express 2. 進一步理解Express 3. Express能做什么 9.2 Express的基本使用 1. 安裝 2. 創建基本的Web服務器 3. 監聽GET請求 4. 監聽POST請求 5. 把內容響應給客戶端 6. 獲取URL中攜帶的查詢參數…

IKAnalyzer分詞插件使用方法

前言 隨著越來越多的大數據網站崛起,特別是一些私人網站都提供了站內搜索,有些人會用elastsearch來實現站內搜索的目的,但是一些小站并沒有那么大的數據提供搜索,在安裝一個 elastsearch 服務未免有點浪費? 因此&#…

ESB 在零售,物流,制造,保險,醫療行業的應用方式

企業服務總線(Enterprise Service Bus, ESB)是一種基于中間件的集成模式,用于實現不同系統之間的集成與通信。ESB通過標準化接口、消息路由、協議轉換和數據轉換等功能,幫助企業實現系統間的無縫對接,提高業務敏捷性。…

vcsa6.7-重置root密碼

客戶反饋vc無法登錄了,登錄環境一看,報錯如下首先想到是證書到期了,瀏覽器確認,確實是證書到期了準備ssh登錄才發現root密碼忘記了,那就先重置root密碼,1、登錄esxi主機找到vcsa6.7機器關機做快照2、開機到…

C++ 賦值與交換法則

在C中,賦值與交換法則(Assignment and Swap Idiom)通常指的是在實現類的賦值操作符(operator)時,結合拷貝構造和交換操作來確保強異常安全保證(Strong Exception Safety Guarantee)的…