InnoDB緩衝池初始化

2021-10-01 12:33:00 字數 3603 閱讀 3391

innodb作為mysql的乙個儲存引擎外掛程式,在啟動mysql資料庫例項時,會呼叫外掛程式提供的初始化函式,innodb啟動時的入口函式是innobase_init

mysql_declare_plugin(innobase)

,

緩衝池初始化通過函式buf_pool_init來完成。mysql支援將緩衝池劃分成多個區域來管理,通過引數innodb_buffer_pool_instances可以進行控制,這裡需要注意到是,如果buf_pool_size設定大於1g,並且srv_buf_pool_instances設定為0時,會自動將srv_buf_pool_instances設定為8. 如果buf_pool_size設定的值小於乙個g時,會自動將數innodb_buffer_pool_instances設定為1.**如下:

if (srv_buf_pool_size >= buf_pool_size_threshold) 

} else

srv_buf_pool_instances = 1;

}

innodb緩衝池在mysql啟動時會進行初始化操作。入口函式為buf_pool_init,下面來看下它的主要實現。

buf_pool_init首先會緩衝池例項陣列指標,它在innodb中通過如下全域性變數來表示:

buf_pool_t*	buf_pool_ptr;
陣列的初始化過程,可以看到它也並沒有直接使用malloc函式來申請記憶體,而是通過ut_zalloc_nokey,innodb基本上通過ut_allocator遮蔽了對作業系統的直接記憶體操作。:

//n_instances對應引數innodb_buffer_pool_instances的值

buf_pool_ptr = (buf_pool_t*) ut_zalloc_nokey(

n_instances * sizeof *buf_pool_ptr);

隨後在迴圈中通過函式buf_pool_init_instance來初始化每乙個緩衝池例項

//其中size表示每乙個緩衝池例項的記憶體大小

for (i = 0; i < n_instances; i++)

}

過程如下:

每次分配乙個chunk的大小,在迴圈中完成對整個緩衝池例項的記憶體分配。

do 

buf_pool->allocator.deallocate_large(

chunk->mem, &chunk->mem_pfx);

}ut_free(buf_pool->chunks);

buf_pool_mutex_exit(buf_pool);

return(db_error);

}buf_pool->curr_size += chunk->size;

} while (++chunk < buf_pool->chunks + buf_pool->n_chunks);

函式buf_chunk_init負責完成每乙個chunk的記憶體分配。

buf_chunk_init需要重新計算本次需要分配的記憶體大小,因為除了要申請使用者指定的記憶體大小外,還要申請每乙個記憶體塊控制區域(buf_block_t)的記憶體,如下:

/* round down to a multiple of page size,

although it already should be. */

mem_size = ut_2pow_round(mem_size, univ_page_size);

/* reserve space for the block descriptors. */

mem_size += ut_2pow_round((mem_size / univ_page_size) * (sizeof *block)

+ (univ_page_size - 1), univ_page_size);

buf_chunk_t中的mem指向分配到的記憶體起始位置。

chunk->mem = buf_pool->allocator.allocate_large(mem_size,

&chunk->mem_pfx);

allocate_large最終通過呼叫os_mem_alloc_large進行大記憶體的分配

size = getpagesize();

/* align block size to system page size */

ut_ad(ut_is_2pow(size));

size = *n = ut_2pow_round(*n + (size - 1), size);

ptr = mmap(null, size, prot_read | prot_write,

map_private | os_map_anon, -1, 0);

計算每乙個chunk中真正會有多少個資料頁,以及資料頁面的起始位置

最終採用mmap的方式來進行記憶體的申請,並且會記錄在innodb 的status中,

total large memory allocated 140836864
初始化每個block,並且新增到free list的尾部,如下:

for (i = chunk->size; i--; )
free list實際上是乙個雙向鍊錶,innodb的雙線鍊錶在很多地方會用到。

鍊錶新增元素的**

template void

list& list,

typename list::elem_type* elem,

functor get_node)

list.end = elem;

if (list.start == 0)

++list.count;

}

緩衝池初始化後的記憶體分布圖

當讀者看完緩衝池的初始化過程後,不難發現,innodb需要很多額外的空間來管理使用者指定大小的記憶體。

在debug模式下,這部分的記憶體占用高達4.9%之多,意味著你為innodb_buffer_pool_size設定為100g,則需要額外的5g的記憶體空間用於這100g記憶體的管理和控制。

innodb的緩衝池(buffer pool)

緩衝區是主記憶體中儲存訪問的表和索引的區域。緩衝池允許經常訪問的資料直接從記憶體處理,更加高效。為了提高大容量讀取操作的效率,緩衝池被劃分為可以容納多行資料的頁 page 為了高效管理快取,緩衝池被實現為頁 page 的列表,快取刪除用lru演算法的變種實現。下圖為緩衝池的結構 head部儲存的是最...

執行緒池初始化引數

執行緒池初始化引數 學習了 int corepoolsize 該執行緒池中核心執行緒數最大值 int maximumpoolsize 該執行緒池中線程總數最大值 long keepalivetime 該執行緒池中非核心執行緒閒置超時時長 timeunit unit keepalivetime的單位 ...

執行緒池初始化引數

執行緒池初始化引數 學習了 int corepoolsize 該執行緒池中核心執行緒數最大值 int maximumpoolsize 該執行緒池中線程總數最大值 long keepalivetime 該執行緒池中非核心執行緒閒置超時時長 timeunit unit keepalivetime的單位 ...