首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL 內核深度解析:緩沖池 Buffer Pool 架構全景與核心組件詳解

     編輯:MySQL 綜合教學

MySQL 內核深度解析:緩沖池 Buffer Pool 架構全景與核心組件詳解

MySQL 內存管理系統龐大而先進,在 mem0pool.c 文件頭部註釋中即有詳細說明。整體可劃分為四大管理部分,包含九大核心內存區域。本文將從緩沖池(Buffer Pool)切入,系統闡述其架構設計、五大功能模塊、四大核心結構體、六大關鍵鏈表及伙伴系統機制,為後續 LRU、刷新、讀取等專題分析奠定基礎。

MySQL 內存子系統全景圖

九大內存區域:

  1. Buffer Pool(緩沖池)
  2. Parsed and optimized SQL statements(解析優化後的 SQL)
  3. Data dictionary cache(數據字典緩存)
  4. Log buffer(日志緩衝)
  5. Locks for each transaction(事務鎖)
  6. Hash table for the adaptive index(自適應索引哈希表)
  7. State and buffers for each SQL query(查詢狀態與緩衝)
  8. Session for each user(用戶會話)
  9. Stack for each OS thread(線程棧)

四大管理部分:

  1. Buffer Pool: 獨立設置大小
  2. Log Buffer: 獨立設置大小
  3. Common Pool: 除上述 1、2、8 之外的所有區域(解析 SQL、數據字典、事務鎖、自適應哈希、查詢緩衝等)
  4. Session 信息: 可視為 Common Pool 一部分

Redo 日志緩衝由 Redo 子系統單獨管理;Buffer Pool 結構最複雜,內容最多;Common Pool 管理除 Buffer Pool、Log Buffer、Session 外的所有區域。

MySQL 內存子系統架構圖

Buffer Pool 子系統五大核心模塊

Buffer Pool 五大模塊架構圖

  1. 緩沖池例程常規管理
    核心協調模塊,管理多實例,協調其餘四模塊運行,向存儲、事務、Redo 日志、主線程等外部子系統提供調用接口。
  2. LRU 鏈表管理
    管理基礎控制單元(buf_block_struct、buf_page_struct)在非壓縮/壓縮 LRU 鏈表中的生命周期。核心功能:節點增刪 → 衍生分配/釋放塊 → 15 個外部主調用函數 + 14 個內部輔助函數(佔 LRU 總函數 60%+)。
  3. 刷新機制
    與底層 IO 交互最緊密,直接執行刷新動作。兩種刷新模式:
    • BUF_FLUSH_LRU:通過 LRU 鏈表刷新
    • BUF_FLUSH_LIST:通過 Flush 鏈表刷新
    包含 Flush 鏈表管理(節點增刪)、單塊刷新、鄰近頁刷新、Doublewrite 組件刷新三大功能,提供外部接口供事務/Mini-事務 Commit 時插入髒塊。
  4. 伙伴系統
    並非統一內存分配器,僅服務於壓縮頁(buf_page_struct.zip.data)的內存分配。但極其關鍵:Buffer Pool 最終服務於文件存儲、事務管理、主進程調度等外部接口,它們都需對頁中記錄進行讀寫。伙伴系統分配後,還需根據運行需要進行壓縮頁↔非壓縮頁轉換,是極端重要的組件。
  5. 讀緩存
    功能簡單直接:單頁異步讀、隨機讀、線性預讀。運行時配合 LRU/Unzip_LRU 進行節點增刪、移尾操作,自然涉及 Flush 鏈表刷新動作。

四大核心結構體深度解析

四大核心結構體關係圖

  1. 緩沖池控制實例 buf_pool_struct
    實例管理核心數據結構,包含:
    • 6 大鏈表表頭(UT_LIST_BASE_NODE_T)
    • 異步 IO 刷新條件變量(os_event_t)
    • LRU 與 Flush 鏈表互斥體
    • 壓縮/非壓縮頁哈希表
    • 關鍵字段:LRU_old_ratio、LRU_list_mutex、page_hash_latch、free_list_mutex、page_hash、flush_list、free、LRU 等
    結構體內容龐大,後續各模塊分析時逐步引用解釋。
  2. 底層內存分配單元 buf_chunk_struct
    最貼近 OS 內存分配,常被忽視但極其重要。所有 buf_block_struct 掛載於 6 大鏈表並由 buf_pool_struct 管理,但其初始內存分配動作均在 buf_chunk_struct 初始化階段完成。它是 Buffer Pool 最基礎的內存分配單元。
    struct buf_chunk_struct {
        ulint mem_size;  // 分配的塊大小
        ulint size;      // frames[] 和 blocks[] 的大小
        void* mem;       // 指向為 frames 分配的內存區域
        buf_block_t* blocks; // 指向 buf_block_t 數組
    };
  3. 非壓縮頁控制塊 buf_block_struct
    管理與壓縮頁控制塊分離。包含:
    • buf_page_t page:壓縮頁結構體引用(必須為首字段,便於哈希表指向)
    • byte* frame:指向大小為 UNIV_PAGE_SIZE、地址對齊的緩衝頁幀(**Buffer Pool 服務的核心**,所有修改針對此內存區,寫回磁盤由異步 IO 處理)
    • Unzip_LRU 鏈表節點、讀寫鎖、互斥體等
    是實現 Buffer Pool 核心接口功能的關鍵控制單元。
  4. 壓縮頁控制塊 buf_page_struct
    理論上非壓縮頁是壓縮頁子集。核心操作在非壓縮頁進行,故不含互斥體,但為一致性實現鎖計數器。關鍵字段:
    • 表空間 ID (space) 與頁偏移量 (offset)
    • 頁狀態、刷新類型 (flush_type:BUF_FLUSH_LRU/BUF_FLUSH_LIST)、IO 固定類型 (io_fix)、緩衝固定計數 (buf_fix_count)
    • 壓縮頁引用、所在哈希表
    • 5 大鏈表節點(free、flush_list、zip_list、LRU、unzip_LRU 除外)
    • 是否處於 OLD_LRU 端、是否崩潰頁、初次訪問時間等

六大關鍵鏈表運作機制

六大鏈表關係圖

  1. 空閒鏈表 (buf_pool->free)
    三大核心鏈表之一。系統初始化時唯一顯式初始化的鏈表。首個 LRU 節點必從免費鏈表獲取。Flush 模塊髒頁刷新完成後,LRU 節點清除或移尾待清除,最終歸歸免費鏈表。
  2. LRU 鏈表 (buf_pool->LRU)
    三大核心鏈表之二。LRU 為空時從免費鏈表取節點,異步 IO 讀入頁並加入 LRU。長度過大時尾部刷新,失敗則直接通過 LRU 刷髒頁(BUF_FLUSH_LRU)。Flush 節點釋放後同步移除 LRU 髒塊。LRU、免費、Flush 三鏈表與五模塊千絲萬縷。
  3. 非壓縮 LRU 鏈表 (buf_pool->unzip_LRU)
    LRU 子集。壓縮頁需解壓進行記錄級讀寫時發揮作用。在 unzip_LRU 中必在 LRU 中,反之不一定。
  4. 髒塊鏈表 (buf_pool->flush_list)
    三大核心鏈表之三,LRU 子集。事務/Mini-事務 Commit 成功意味著內存寫入成功,髒頁必入 Flush 鏈表,等待異步 IO 線程(主線程子系統之一)刷新。Linux 原生 AIO 與 Heikki Tuuri 實現的模擬 AIO(條件變量)均由 buf_pool_struct 管理。
  5. 未修改壓縮塊鏈表 (buf_pool->zip_clean)
    僅用於調試功能。
  6. 伙伴系統空閒鏈表 (buf_pool->zip_free[])
    最特殊:根節點為指針數組(4 層:1024、2048、4096、8192)。伙伴系統精髓:按 2 倍數合併拆分鄰近內存塊,實現高效管理、低代碼複雜度。每層基節點僅管理同尺寸塊。

後續規劃與總結

Buffer Pool 整體概述暫告段落。後續將陸續深入分析:LRU 替換算法詳解、刷新機制實現、伙伴系統內存管理、讀取路徑與預讀策略、雙寫緩衝、實例管理與擴展性設計等專題。歡迎指正文中任何錯誤,讓我們共同探索 MySQL 內核奧秘。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved