InnoDBソース分析--バッファ(三)
8876 ワード
転載は原文のリンクを添付してください.http://www.cnblogs.com/wingsless/p/5582063.html
昨日はInnoDBバッファの予読について書きました.
線形予読はこの関数によって実現される:buf_read_.アホードlinearは、ランダム予読と同様に、まず領域境界を決めます.この境界内に訪問されたpageがしきい値に達すると、予読動作をトリガします.境界のアルゴリズムはBUF_によって実行される.READ_AHEAD_LINEAR_AREA決定:
これでリニア予読が完了しました.
ランダムで予読しても、線形で予読しても、システムの圧力が大きい時に予読しないような条件があります.
昨日はInnoDBバッファの予読について書きました.
線形予読はこの関数によって実現される:buf_read_.アホードlinearは、ランダム予読と同様に、まず領域境界を決めます.この境界内に訪問されたpageがしきい値に達すると、予読動作をトリガします.境界のアルゴリズムはBUF_によって実行される.READ_AHEAD_LINEAR_AREA決定:
low = (offset / BUF_READ_AHEAD_LINEAR_AREA)
* BUF_READ_AHEAD_LINEAR_AREA;
high = (offset / BUF_READ_AHEAD_LINEAR_AREA + 1)
* BUF_READ_AHEAD_LINEAR_AREA;
if ((offset != low) && (offset != high - 1)) {
/* This is not a border page of the area: return */
return(0);
}
なお、offsetが境界上にないと予読は行われないので、ランダム予読とは異なる.線形プリ読みは、実はシーケンス的に読み取られ、offsetがlow位置にあれば、逆順にpageを読み、offsetがハイテンション位置にあれば、順にpageを読みます.読み取ったページごとに判断を行いますが、訪問したページの数が上記の閾値に達すると、線形予読の条件が満たされ、閾値に達しないと予読は行われません.コードは以下の通りです. asc_or_desc = 1; //
if (offset == low) {
asc_or_desc = -1; // offset low ,
}
fail_count = 0;
for (i = low; i < high; i++) {
block = buf_page_hash_get(space, i); //
if ((block == NULL) || !block->accessed) {
/* Not accessed */
fail_count++; //
} else if (pred_block
&& (ut_ulint_cmp(block->LRU_position,
pred_block->LRU_position)
!= asc_or_desc)) {
/* Accesses not in the right order */
fail_count++;
pred_block = block;
}
}
if (fail_count > BUF_READ_AHEAD_LINEAR_AREA
- BUF_READ_AHEAD_LINEAR_THRESHOLD) { // ,
/* Too many failures: return */
mutex_exit(&(buf_pool->mutex));
return(0);
}
前にある本で見たことがありますが、メモリのページは物理的に連続しているのではなく、論理的に連続しているという意味です.ここの線形予読には、これらのページは物理的にも連続していなければならない. pred_offset = fil_page_get_prev(frame);
succ_offset = fil_page_get_next(frame);
mutex_exit(&(buf_pool->mutex));
if ((offset == low) && (succ_offset == offset + 1)) {
/* This is ok, we can continue */
new_offset = pred_offset; // ,
} else if ((offset == high - 1) && (pred_offset == offset - 1)) {
/* This is ok, we can continue */
new_offset = succ_offset; // ,
} else {
/* Successor or predecessor not in the right order */
return(0);
}
ここはこのようなところです.まずfil_を利用します.page_ゲットするprevとfil_page_ゲットするnext関数がoffset->frameを読み取った後、または前の4つのbytesは、結果が順序条件を満たしていれば、線形予読を継続することができます. for (i = low; i < high; i++) {
/* It is only sensible to do read-ahead in the non-sync
aio mode: hence FALSE as the first parameter */
if (!ibuf_bitmap_page(i)) {
count += buf_read_page_low(
&err, FALSE,
ibuf_mode | OS_AIO_SIMULATED_WAKE_LATER,
space, tablespace_version, i);
if (err == DB_TABLESPACE_DELETED) {
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Warning: in"
" linear readahead trying to access
"
"InnoDB: tablespace %lu page %lu,
"
"InnoDB: but the tablespace does not"
" exist or is just being dropped.
",
(ulong) space, (ulong) i);
}
}
}
リニア予読はやはりbuf_を利用しました.read_.page_low関数は、この点はランダム予読と同じで、非同期方式です.これでリニア予読が完了しました.
ランダムで予読しても、線形で予読しても、システムの圧力が大きい時に予読しないような条件があります.
if (buf_pool->n_pend_reads
> buf_pool->curr_size / BUF_READ_AHEAD_PEND_LIMIT) {
mutex_exit(&(buf_pool->mutex));
return(0);
}
ここでは、pend読み取り数がbuf_より大きいと規定しています.pool->curr_sizeの半分の時は予読しません.似たような条件はまだたくさんあります.コードの中にあります.ここでは書きません.