首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

InnoDB 動態陣列內部實現深度解析:dyn0dyn.c 核心資料結構與記憶體管理

     編輯:MySQL 資料庫相關知識

核心檔案與用途

  • dyn0dyn.h:介面定義
  • dyn0dyn.ic:內聯函數
  • dyn0dyn.c:實現主體

用途:MTR (Mini-Transaction) 鎖資訊、Redo Log 緩衝 的動態線性位元組陣列。

資料結構定義

#define DYN_ARRAY_DATA_SIZE 512  // 固定區塊大小

typedef struct dyn_block_struct dyn_block_t;
typedef dyn_block_t dyn_array_t;  // 陣列頭即第一個區塊

struct dyn_block_struct {
    mem_heap_t* heap;              // 記憶體堆(首區塊持有)
    ulint used;                    // 已使用位元組數
    byte data[DYN_ARRAY_DATA_SIZE]; // 資料區
    UT_LIST_BASE_NODE_T(dyn_block_t) base; // 雙向鏈表頭(僅首區塊)
    UT_LIST_NODE_T(dyn_block_t) list;      // 鏈表節點
#ifdef UNIV_DEBUG
    ulint buf_end;
    ulint magic_n;                 // 魔數驗證
#endif
};

關鍵操作流程

1. 建立陣列

dyn_array_t* dyn_array_create(dyn_array_t* arr) {
    ut_ad(arr);
    arr->heap = NULL;      // 延遲分配
    arr->used = 0;
    return arr;
}

2. 追加資料

// 邏輯簡化
void dyn_array_append(dyn_array_t* arr, const void* src, ulint len) {
    if (arr->used + len <= DYN_ARRAY_DATA_SIZE) {
        memcpy(arr->data + arr->used, src, len);
        arr->used += len;
    } else {
        // 切分:先填滿當前區塊
        ulint first_part = DYN_ARRAY_DATA_SIZE - arr->used;
        memcpy(arr->data + arr->used, src, first_part);
        arr->used = DYN_ARRAY_DATA_SIZE;
        
        // 剩餘部份分配新區塊
        dyn_block_t* block = dyn_array_add_block(arr);
        memcpy(block->data, (byte*)src + first_part, len - first_part);
        block->used = len - first_part;
    }
}

3. 新增區塊

dyn_block_t* dyn_array_add_block(dyn_array_t* arr) {
    if (arr->heap == NULL) {
        // 首次:初始化鏈表,首區塊加入
        UT_LIST_INIT(arr->base);
        UT_LIST_ADD_FIRST(list, arr->base, arr);
        arr->heap = mem_heap_create(1024);  // 建立記憶體堆
    }
    // 從堆分配新區塊
    dyn_block_t* block = (dyn_block_t*)mem_heap_alloc(arr->heap, sizeof(dyn_block_t));
    block->heap = arr->heap;  // 共享堆
    block->used = 0;
    UT_LIST_ADD_LAST(list, arr->base, block);
    return block;
}

記憶體管理特點

  • 首區塊雙重身分:既是陣列頭,也是鏈表第一個節點
  • 統一記憶體堆:所有區塊從首區塊 heap 分配,銷毀時一次釋放
  • 固定區塊大小:512 bytes,超過則切分(主要用於 Redo Log 大記錄)
  • 除錯魔數:magic_n 防止記憶體越界破壞

使用場景

效能考量

  • 區塊大小 512B 平衡記憶體碎片與分配頻率
  • 避免頻繁 mem_heap_alloc:批次操作時預估大小預分配
  • MTR 提交時整體寫入 Redo Log,減少 fsync 次數
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
場景說明
MTR 鎖資訊儲存事務持有的鎖結構,提交時寫入 Redo Log
Redo Log 緩衝Log Buffer 寫入前暫存,支援大記錄切分
Undo Log 暫存部分場景下的動態擴展