Mysql Innodb中的Linux native非同步I/O(一) 記憶體結構的初始化
水平有限,有誤請指出
一、前言
在5.7中Innodb非同步I/O的記憶體結構發生了一些變化特別是非同步I/O陣列和以前的結構體不同變為了類叫做AIO類但是換湯不換藥只是將一些方法進行了封裝,而非同步i/o實際的請求放到了Slot結構體它們分別對應了5.6 os_aio_array_t和os_aio_slot_t,這裡不準備詳細介紹每一個屬性的含義,因為在核心月報中淘寶已經給出,5.7基本也是一樣的連線如下:
同時我這裡也是討論關於Linux native的部分對於innodb自己模擬的非同步I/O不做分析,因為用得不多,並且自己能力也有限。但是這裡還是需要明確幾個概念
本文簡書地址
二、幾個基本概念
-
什麼是Linux native I/O
參考我的文章:
http://blog.itpub.net/7728585/viewspace-2147684/
或者參考其他文章 -
MYSQL中的非同步I/O執行緒
我以前一直搞不清楚這幾個執行緒的作用,為了搞清楚這個我才決定好好學習一下非同步I/O
如下面的引數設定
mysql> show variables like '%io_threads%'; +-------------------------+-------+ | Variable_name | Value | +-------------------------+-------+ | innodb_read_io_threads | 2 | | innodb_write_io_threads | 2 | +-------------------------+-------+
我在本資料中實際設定了2個read 非同步i/o執行緒和2個write非同步I/O執行緒此外都包含一個log和ibuf非同步I/O執行緒在資料庫中我們也可以查詢到這6個非同步I/O執行緒
mysql> select a.thd_id,b.THREAD_OS_ID,a.user ,a.conn_id,b.TYPE,a.source,a.program_name from sys.processlist a,performance_schema.threads b where b.thread_id=a.thd_id and user like '%io%'; +--------+--------------+------------------------+---------+------------+--------------------+--------------+ | thd_id | THREAD_OS_ID | user | conn_id | TYPE | source | program_name | +--------+--------------+------------------------+---------+------------+--------------------+--------------+ | 3 | 14059 | innodb/io_ibuf_thread | NULL | BACKGROUND | NULL | NULL | | 4 | 14060 | innodb/io_log_thread | NULL | BACKGROUND | sync0debug.cc:1296 | NULL | | 5 | 14061 | innodb/io_read_thread | NULL | BACKGROUND | NULL | NULL | | 6 | 14062 | innodb/io_read_thread | NULL | BACKGROUND | NULL | NULL | | 7 | 14063 | innodb/io_write_thread | NULL | BACKGROUND | sync0debug.cc:1296 | NULL | | 8 | 14064 | innodb/io_write_thread | NULL | BACKGROUND | NULL | NULL | +--------+--------------+------------------------+---------+------------+--------------------+--------------+
- AIO類、執行緒、Slot的關係
首先一個AIO類對應了一個型別的非同步,比如ibuf/log/read/write都對應一個AIO類,並且在類的最後用一個類的靜態全域性成員進行指向如下:
/** Insert buffer */ static AIO* s_ibuf; /** Redo log */ static AIO* s_log; /** Reads */ static AIO* s_reads; /** Writes */ static AIO* s_writes;
而我們的非同步I/O執行緒實際上有6個也就是s_reads包含了2個執行緒/s_writes包含了2個執行緒,那麼執行緒引入了一個叫做local segment的概念,實際上每一個執行緒對應了一個local segment,而在AIO下面掛的就是一個Slot的vertor陣列,陣列的大小和每種型別的執行緒個數(local segment)和每個執行緒最大的Slot有關,看原始碼中對最大的Slot的定義如下:
8 * OS_AIO_N_PENDING_IOS_PER_THREAD
其中宏定義OS_AIO_N_PENDING_IOS_PER_THREAD=32
那麼對於s_ibuf和s_log因為只有一個執行緒(local segment)那麼就有256個Slot,而s_reads和s_writes當前我的資料庫各有2個執行緒(local segment)那麼就有2*256=512個Slot.
-
global segment
這個概念主要和模擬的非同步I/O有關,如果我當前有6個非同步I/O執行緒那麼global segment就是6,因為在進行初始化呼叫AIO::start的時候其編號總是固定的及0和1對應瞭然後是read和write執行緒個數,那麼由global segment到local segment的換算也變得簡單了可以參考AIO::get_segment_no_from_slot.
如果沒有顯示指定本文所有segment均指local segment
三、記憶體結構的初始化
整個記憶體結構的初始化是從由innobase_start_or_create_for_mysql呼叫的下面程式碼開始的如下:
點選(此處)摺疊或開啟
-
if (!os_aio_init(srv_n_read_io_threads,
-
srv_n_write_io_threads,
-
SRV_MAX_N_PENDING_SYNC_IOS)) {
-
-
ib::error() << "Cannot initialize AIO sub-system";
-
-
return(srv_init_abort(DB_ERROR));
- }
1、os_aio_init 由innobase_start_or_create_for_mysql ()調入
本資料庫呼叫棧幀:
點選(此處)摺疊或開啟
-
#0 os_aio_init (n_readers=2, n_writers=2, n_slots_sync=100) at /root/mysql5.7.14/percona-server-5.7.14-7/storage/innobase/os/os0file.cc:6734
- #1 0x0000000001b8dde1 in innobase_start_or_create_for_mysql () at /root/mysql5.7.14/percona-server-5.7.14-7/storage/innobase/srv/srv0start.cc:1792
點選(此處)摺疊或開啟
-
bool
-
os_aio_init(
-
ulint n_readers,
-
ulint n_writers,
-
ulint n_slots_sync)
-
{
-
/* Maximum number of pending aio operations allowed per segment */
-
ulint limit = 8 * OS_AIO_N_PENDING_IOS_PER_THREAD; //這裡我們發現了limit的定義也就是
-
//一個執行緒(local segments)包含的slot個數及256
-
.....
-
return(AIO::start(limit, n_readers, n_writers, n_slots_sync));
- }
這個函式的主要功能就是呼叫AIO::start下面我們進行學習。
2、 AIO::start 由os_aio_init調入
本資料庫呼叫棧幀:
點選(此處)摺疊或開啟
-
#1 0x0000000001a7db18 in AIO::start (n_per_seg=256, n_readers=2, n_writers=2, n_slots_sync=100)
-
at /root/mysql5.7.14/percona-server-5.7.14-7/storage/innobase/os/os0file.cc:6610
- #2 0x0000000001a7e289 in os_aio_init (n_readers=2, n_writers=2, n_slots_sync=100) at /root/mysql5.7.14/percona-server-5.7.14-7/storage/innobase/os/os0file.cc:6762
點選(此處)摺疊或開啟
-
bool
-
AIO::start(
-
ulint n_per_seg, //每個segment的slot數量
-
ulint n_readers, //多少個非同步讀I/O執行緒
-
ulint n_writers, //多少個非同步寫I/O執行緒
-
ulint n_slots_sync)
-
{
-
#if defined(LINUX_NATIVE_AIO)
-
/* Check if native aio is supported on this system and tmpfs */
-
//這裡根據引數innodb_use_native_aio設定和是否支援native aio測試進行綜合判斷,即便
-
//引數設定為ON,但是不支援libaio也會將srv_use_native_aio設定為FLASE
-
if (srv_use_native_aio && !is_linux_native_aio_supported()) {
-
-
ib::warn() << "Linux Native AIO disabled.";//這裡出現一個經常看到警告資訊native aio不可用
-
-
srv_use_native_aio = FALSE;
-
-
}
-
#endif /* LINUX_NATIVE_AIO */
-
-
srv_reset_io_thread_op_info(); /* 重置執行緒狀態設定為not start */
-
-
/* 這裡開始初始化AIO read執行緒 我這裡設定是 nreaders=2個read執行緒 n_per_seg=每個執行緒 256個slot */
-
s_reads = create(
-
LATCH_ID_OS_AIO_READ_MUTEX, n_readers * n_per_seg, n_readers);
-
-
if (s_reads == NULL) {
-
return(false);
-
}
-
-
/* 這裡進行只讀檢測 如果是隻讀則log 和 ibuf 非同步執行緒不啟用
-
由邏輯srv_read_only_mode ? 0 : 2 進行控制
-
下面主要開始設定執行緒的名字如果沒有log和ibuf則
-
readers從下標0開始否則從下標2開始 */
-
Array of English strings describing the current state of an i/o handler thread */
-
const char* srv_io_thread_op_info[SRV_MAX_N_IO_THREADS];
-
const char* srv_io_thread_function[SRV_MAX_N_IO_THREADS];
-
*/
-
ulint start = srv_read_only_mode ? 0 : 2;
-
ulint n_segs = n_readers + start;
-
-
/* 0 is the ibuf segment and 1 is the redo log segment. */
-
for (ulint i = start; i < n_segs; ++i) {
-
ut_a(i < SRV_MAX_N_IO_THREADS);
-
srv_io_thread_function[i] = "read thread";
-
}
-
-
ulint n_segments = n_readers;
-
-
-
/* 如果沒有設定只讀,這裡開始不會初始化ibuf和log aio結構 */
-
-
if (!srv_read_only_mode) {
-
-
s_ibuf = create(LATCH_ID_OS_AIO_IBUF_MUTEX, n_per_seg, 1);
-
-
if (s_ibuf == NULL) {
-
return(false);
-
}
-
-
++n_segments;
-
-
srv_io_thread_function[0] = "insert buffer thread";
-
-
s_log = create(LATCH_ID_OS_AIO_LOG_MUTEX, n_per_seg, 1);
-
-
if (s_log == NULL) {
-
return(false);
-
}
-
-
++n_segments;
-
-
srv_io_thread_function[1] = "log thread";
-
-
} else {
-
s_ibuf = s_log = NULL;
-
}
-
-
/* 依然是一樣的方式初始化write thread AIO結構 */
-
-
s_writes = create(
-
LATCH_ID_OS_AIO_WRITE_MUTEX, n_writers * n_per_seg, n_writers);
-
-
if (s_writes == NULL) {
-
return(false);
-
}
-
-
n_segments += n_writers; //這裡我們得到最終的GLOBAL SEGMENT = 2+1+1+2 = 6
-
-
for (ulint i = start + n_readers; i < n_segments; ++i) {
-
ut_a(i < SRV_MAX_N_IO_THREADS);
-
srv_io_thread_function[i] = "write thread";
-
}
-
-
ut_ad(n_segments >= static_cast<ulint>(srv_read_only_mode ? 2 : 4));
-
-
s_sync = create(LATCH_ID_OS_AIO_SYNC_MUTEX, n_slots_sync, 1);/*這個執行緒功能還需要看看n_slots_sync=100 */
-
-
if (s_sync == NULL) {
-
-
return(false);
-
}
-
-
os_aio_n_segments = n_segments; //=6
-
-
os_aio_validate();
-
//開始分配event,他是cond和mutex的封裝
-
os_aio_segment_wait_events = static_cast<os_event_t*>(
-
ut_zalloc_nokey(
-
n_segments * sizeof *os_aio_segment_wait_events)); //這裡分配n_segments 個數的條件變數記憶體這裡是6個
-
/*
-
Array of events used in simulated AIO
-
static os_event_t* os_aio_segment_wait_events = NULL;
-
最後指標給了這樣一個內部全域性靜態變數
-
*/
-
-
-
if (os_aio_segment_wait_events == NULL) {
-
-
return(false);
-
}
-
-
/*
-
對其進行初始化這裡我們明確的看出每一個SEGMENTS 也就是每一個執行緒都對應一個條件變數和MUTEX
-
他的具體作用和模擬非同步I/O有關如AIO::wake_simulated_handler_thread呼叫
-
*/
-
for (ulint i = 0; i < n_segments; ++i) {
-
os_aio_segment_wait_events[i] = os_event_create(0);
-
}
-
-
os_last_printout = ut_time();
-
-
return(true);
- }
這裡我們可以看到實際上還是呼叫核心函式AIO::create,在AIO::create呼叫成果後就將各個型別的AIO物件的指標賦予給了幾個類靜態全域性指標用於後面呼叫
3、AIO::create 由AIO::start 調入
本資料庫呼叫棧幀:
點選(此處)摺疊或開啟
-
#0 AIO::create (id=LATCH_ID_OS_AIO_READ_MUTEX, n=512, n_segments=2) at /root/mysql5.7.14/percona-server-5.7.14-7/storage/innobase/os/os0file.cc:6529
- #1 0x0000000001a7db18 in AIO::start (n_per_seg=256, n_readers=2, n_writers=2, n_slots_sync=100) at /root/mysql5.7.14/percona-server-5.7.14-7/storage/innobase/os/os0file.cc:6610
點選(此處)摺疊或開啟
-
AIO*
-
AIO::create(
-
latch_id_t id,
-
ulint n, //某個型別AIO物件應該包含的SLOT數量
-
ulint n_segments) //執行緒數量(segment)
-
{
-
if ((n % n_segments)) { //這裡先做了一個保障校驗n是否是n_segments的倍數
-
-
ib::error()
-
<< "Maximum number of AIO operations must be "
-
<< "divisible by number of segments";
-
-
return(NULL);
-
}
-
AIO* array = UT_NEW_NOKEY(AIO(id, n, n_segments)); //功能1、呼叫建構函式AIO(id, n, n_segments)
-
if (array != NULL && array->init() != DB_SUCCESS) { //功能2、呼叫array->init()
-
-
UT_DELETE(array);
-
-
array = NULL;
-
}
-
return(array);
- }
我們發現本函式有2個主要功能
- 1、呼叫建構函式AIO(id, n, n_segments)
-
2、呼叫array->init()
所以我們需要分別討論
首先來看AIO(id, n, n_segments)
4、AIO::AIO 由AIO::create 調入
點選(此處)摺疊或開啟
-
#0 AIO::AIO (this=0x32ea658, id=LATCH_ID_OS_AIO_READ_MUTEX, n=512, segments=2) at /root/mysql5.7.14/percona-server-5.7.14-7/storage/innobase/os/os0file.cc:6396
-
#1 0x0000000001a7d862 in AIO::create (id=LATCH_ID_OS_AIO_READ_MUTEX, n=512, n_segments=2)
- at /root/mysql5.7.14/percona-server-5.7.14-7/storage/innobase/os/os0file.cc:6538
原始碼及註釋如下:
點選(此處)摺疊或開啟
-
AIO::AIO(
-
latch_id_t id,
-
ulint n, //某個型別AIO物件應該包含的SLOT數量
-
ulint segments)//執行緒數量(segment)
-
:
-
m_slots(n), //定義出多少個slot這裡是512個因為我有2個io_read執行緒每個執行緒256個slot,分配記憶體
-
m_n_segments(segments), //多少個segments 我是2個io_read也就是2個
-
m_n_reserved(),//設定為0
-
m_aio_ctx(),//設定為NULL
-
m_events(m_slots.size()) //完成events陣列大小設定為slot的個數
-
{
-
....
-
mutex_create(id, &m_mutex); //根據傳入的ID建立mutex 本MUTEX 保護多個執行緒同時使用本陣列
-
-
m_not_full = os_event_create("aio_not_full");//建立所謂的event,在這個event中封裝了條件變數cond和mutex
-
m_is_empty = os_event_create("aio_is_empty");//建立所謂的event,在這個event中封裝了條件變數cond和mutex
-
-
memset(&m_slots[0], 0x0, sizeof(m_slots[0]) * m_slots.size());//將整個slot記憶體空間全部清0
-
#ifdef LINUX_NATIVE_AIO
-
memset(&m_events[0], 0x0, sizeof(m_events[0]) * m_events.size());//將整個events記憶體空間全部清0,他就是io_getevents呼叫需要的
-
#endif /* LINUX_NATIVE_AIO */
-
-
os_event_set(m_is_empty); //透過brocast喚醒,所有堵塞在m_is_empty上的執行緒進行處理
- }
經過本函式我們發現在AIO這個結構體中的成員基本都進行了初始化
m_slots/m_n_segments/m_n_reserved/m_aio_ctx/m_events/m_mutex/m_not_full/m_is_empty
只是這些某些還沒有意義比如m_aio_ctx
接下來我們看第二個功能 AIO::init()
5、AIO::init() 由AIO::create調入本資料庫呼叫棧幀:
點選(此處)摺疊或開啟
-
#0 AIO::init (this=0x32ea658) at /root/mysql5.7.14/percona-server-5.7.14-7/storage/innobase/os/os0file.cc:6493
-
#1 0x0000000001a7d8a2 in AIO::create (id=LATCH_ID_OS_AIO_READ_MUTEX, n=512, n_segments=2)
- at /root/mysql5.7.14/percona-server-5.7.14-7/storage/innobase/os/os0file.cc:6540
原始碼及註釋如下:
點選(此處)摺疊或開啟
-
/** Initialise the array */
-
dberr_t
-
AIO::init()
-
{
-
ut_a(!m_slots.empty());//這裡斷言是否為空,不可能為空除非遇到故障
-
-
#ifdef _WIN32
-
ut_a(m_handles == NULL);
-
-
m_handles = UT_NEW_NOKEY(Handles(m_slots.size()));
-
#endif /* _WIN32 */
-
-
if (srv_use_native_aio) { //這個並非引數設定而是前面說的引數設定和innodb檢測是否支援native aio的綜合考慮
-
#ifdef LINUX_NATIVE_AIO
-
dberr_t err = init_linux_native_aio();//功能1 如果開啟了innodb_use_native_aio引數並且支援native aio進行呼叫init_linux_native_aio()
-
-
if (err != DB_SUCCESS) {
-
return(err);
-
}
-
-
#endif /* LINUX_NATIVE_AIO */
-
}
-
- return(init_slots()); //功能2 呼叫init_slots()初始化slot記憶體結構
我們發現本函式有2個主要功能
- 1、如果開啟了innodb_use_native_aio引數並且支援native aio進行呼叫init_linux_native_aio()
- 2、呼叫init_slots()初始化slot記憶體結構
下面我們先看看AIO::init_linux_native_aio()呼叫
6、AIO::init_linux_native_aio() 由 AIO::init調入本資料庫呼叫棧幀:
點選(此處)摺疊或開啟
-
#0 AIO::init_linux_native_aio (this=0x32ea658) at /root/mysql5.7.14/percona-server-5.7.14-7/storage/innobase/os/os0file.cc:6460
- #1 0x0000000001a7d701 in AIO::init (this=0x32ea658) at /root/mysql5.7.14/percona-server-5.7.14-7/storage/innobase/os/os0file.cc:6503
點選(此處)摺疊或開啟
-
/** Initialise the Linux Native AIO interface */
-
dberr_t
-
AIO::init_linux_native_aio()
-
{
-
/* Initialize the io_context array. One io_context
-
per segment in the array. */
-
-
ut_a(m_aio_ctx == NULL);
-
-
m_aio_ctx = static_cast<io_context**>(
-
ut_zalloc_nokey(m_n_segments * sizeof(*m_aio_ctx)));//到這裡了我們知道AIO類的屬性已經進行了初始化m_n_segments就是本AIO物件包含的執行緒數量
-
//ibuf和redo非同步為1個,write和read非同步執行緒本系統為2個這由引數控制,這裡為io_context_t
-
//也就是一個執行緒對應一個io_context_t這是Linux native aio必須的
-
-
if (m_aio_ctx == NULL) {
-
return(DB_OUT_OF_MEMORY);
-
}
-
-
io_context** ctx = m_aio_ctx;
-
ulint max_events = slots_per_segment(); //這裡返回每個執行緒最大的event個數用於初始化io_context_t結構體就是return(m_slots.size() / m_n_segments)
-
//及256個
-
-
for (ulint i = 0; i < m_n_segments; ++i, ++ctx) { //進行初始化對每個執行緒的io_context_t呼叫io_steup進行初始化其佇列最大event個數為
-
//return(m_slots.size() / m_n_segments); 也就是256
-
-
if (!linux_create_io_ctx(max_events, ctx)) { //linux_create_io_ctx 主要功能就是初始化io_context_t
-
/* If something bad happened during aio setup
-
we should call it a day and return right away.
-
We don't care about any leaks because a failure
-
to initialize the io subsystem means that the
-
server (or atleast the innodb storage engine)
-
is not going to startup. */
-
return(DB_IO_ERROR);
-
}
-
}
-
-
return(DB_SUCCESS); //最後返回成功,這樣io_context_t也就是AIO結構體中的m_aio_ctx得到了初始化
- }
到這裡io_context_t已經分配,接下來呼叫AIO::init_slots()我們進行分析
7、AIO::init_slots() 由 AIO::init調入
本資料庫呼叫棧幀:
點選(此處)摺疊或開啟
-
#0 AIO::init_slots (this=0x32ea658) at /root/mysql5.7.14/percona-server-5.7.14-7/storage/innobase/os/os0file.cc:6421
- #1 0x0000000001a7d71b in AIO::init (this=0x32ea658) at /root/mysql5.7.14/percona-server-5.7.14-7/storage/innobase/os/os0file.cc:6512
原始碼及註釋如下:
點選(此處)摺疊或開啟
-
/** Initialise the slots */
-
dberr_t
-
AIO::init_slots()
-
{
-
for (ulint i = 0; i < m_slots.size(); ++i) {
-
Slot& slot = m_slots[i]; //使用引用指向第i個元素
-
-
slot.pos = static_cast<uint16_t>(i); //分別初始化為0到m_slots.size()也就是每個slot進行了編號編號為pos
-
-
slot.is_reserved = false; //初始化
-
-
#ifdef WIN_ASYNC_IO //下面是WINDOW的處理不分析
-
-
slot.handle = CreateEvent(NULL, TRUE, FALSE, NULL);
-
-
OVERLAPPED* over = &slot.control;
-
-
over->hEvent = slot.handle;
-
-
(*m_handles)[i] = over->hEvent;
-
-
#elif defined(LINUX_NATIVE_AIO)
-
-
slot.ret = 0; //ret設定0
-
-
slot.n_bytes = 0; //n_bytes設定為0
-
-
memset(&slot.control, 0x0, sizeof(slot.control)); //這裡對iocb結構進行清0操作,其實在AIO::AIO中已經清0了因為iocb並不是指標而是實際的記憶體空間
-
-
#endif /* WIN_ASYNC_IO */
-
}
-
-
return(DB_SUCCESS);
- }
到這裡Linux native 非同步I/O的iocb已經分配個數為256*segment 並且初始化0完成。
四、初始化完成後記憶體圖
如下一張簡圖表示了初始化完成後的記憶體圖:
五、後記
初始化完成後接下來就是如何呼叫了,這個還需要仔細的分析。再開一篇文章進行分析。
那麼最後寫一下如果要用Linux native AIO 需要滿足的條件
- 1、innodb_use_native_aio = ON
- 2、libaio安裝了
- 3、innodb_flush_method O_DIRECT
缺一不可,這些條件很容易達到
作者微信:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7728585/viewspace-2147756/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- MySQL探祕(三):InnoDB的記憶體結構和特性MySql記憶體
- I/O埠和I/O記憶體記憶體
- MySQL InnoDB的記憶體管理MySql記憶體
- MySQL InnoDB記憶體配置MySql記憶體
- MySQL查詢select語句的執行流程以及InnoDB記憶體結構MySql記憶體
- MySQL 配置InnoDB的記憶體分配器MySql記憶體
- Linux裝置驅動中的阻塞和非阻塞I/OLinux
- MySQL整體架構與記憶體結構MySql架構記憶體
- 詳細瞭解 InnoDB 記憶體結構及其原理記憶體
- socket阻塞與非阻塞,同步與非同步、I/O模型非同步模型
- 【Oracle-記憶體管理】-Multiple I/O SlavesOracle記憶體
- 【Mysql】InnoDB 引擎中的資料頁結構MySql
- Oracle 記憶體結構(一)Oracle記憶體
- linux檢視 CPU,記憶體,網路流量和磁碟 I/OLinux記憶體
- MySQL 配置InnoDB主執行緒I/O速率MySql執行緒
- mysql innodb體系結構--初級MySql
- 【基礎篇記憶體結構】oracle10g記憶體結構(一)記憶體Oracle
- 談談對不同I/O模型的理解 (阻塞/非阻塞IO,同步/非同步IO)模型非同步
- Linux libaio 非同步I/OLinuxAI非同步
- 理解JVM(一):記憶體結構JVM記憶體
- 【翻譯】記憶體結構 (一)記憶體
- MySQL 配置後臺InnoDB I/O執行緒數MySql執行緒
- Buffer Cache的記憶體結構記憶體
- Innodb undo之 undo物理結構的初始化
- InfluxDB中的inmem記憶體索引結構解析UX記憶體索引
- 解析記憶體中的高效能圖結構記憶體
- nodejs筆記-非同步I/ONodeJS筆記非同步
- MySQL InnoDB的儲存結構總結MySql
- 記憶體結構記憶體
- 【Mysql】讀書筆記之--innodb_buffer_pool記憶體的管理MySql筆記記憶體
- Oracle中Buffer Cache記憶體結構Oracle記憶體
- JVM的基本結構和JVM的記憶體結構JVM記憶體
- MySQL InnoDB儲存引擎體系結構MySql儲存引擎
- 深入淺出:Linux裝置驅動中的阻塞和非阻塞I/OLinux
- Oracle記憶體結構(一)----SGA的區域資訊Oracle記憶體
- Linux中的記憶體管理Linux記憶體
- JVM學習(一)——記憶體結構JVM記憶體
- JAVA的記憶體模型及結構Java記憶體模型