MySQL Pageの読み取りと淘汰プロセスの分析

4980 ワード


Pageディスクの読み取りとロードの反発
buf_page_get_gen
|    | ==> rw_lock_s_lock(hash_lock);
|    | ==> block = (buf_block_t*) buf_page_hash_get_low(buf_pool, space, offset, fold);
|    | ==> if (block == NULL) rw_lock_s_unlock(hash_lock); 
|        | ==> buf_read_page(space, zip_size, offset)  buf_read_page_low
|            | ==> bpage = buf_page_init_for_read(err, mode, space, zip_size, unzip, tablespace_version, offset);
|                | ==> block = NULL;
|                | ==> buf_pool_mutex_enter(buf_pool);
|                | ==> rw_lock_x_lock(hash_lock);
|                | ==> watch_page = buf_page_hash_get_low(buf_pool, space, offset, fold);
|                | ==> if (watch_page && !buf_pool_watch_is_sentinel(buf_pool, watch_page))
|                    | ==> rw_lock_x_unlock(hash_lock);
|                | ==> rw_lock_x_unlock(hash_lock);
|                | ==> data = buf_buddy_alloc(buf_pool, zip_size, &lru);
|                    | ==> buf_buddy_alloc_low(buf_pool, buf_buddy_get_slot(size), lru));
|                        | ==> block = buf_LRU_get_free_only(buf_pool);
|                | ==> rw_lock_x_lock(hash_lock);
|                | ==> /* If buf_buddy_alloc() allocated storage from the LRU list, it released and reacquired buf_pool->mutex.  Thus, we must check the page_hash again, as it may have been modified. */
|                | ==> if (UNIV_UNLIKELY(lru)) {
|                    | ==> watch_page = buf_page_hash_get_low(buf_pool, space, offset, fold);
|                | ==> if (watch_page && !buf_pool_watch_is_sentinel(buf_pool, watch_page)) rw_lock_x_unlock(hash_lock); watch_page = NULL; buf_buddy_free(buf_pool, data, zip_size);
|                | ==> HASH_INSERT(buf_page_t, hash, buf_pool->page_hash, fold, bpage);
|                | ==> rw_lock_x_unlock(hash_lock);
|                | ==> buf_LRU_add_block(bpage, TRUE/* to old blocks */);
|                | ==> buf_pool_mutex_exit(buf_pool);
|    | ==> buf_block_fix(fix_block);
|        | ==> #ifdef PAGE_ATOMIC_REF_COUNT
|        | ==> 	os_atomic_increment_uint32(&block->page.buf_fix_count, 1);
|        | ==> #else
|        | ==> 	ib_mutex_t*	block_mutex = buf_page_get_mutex(&block->page);
|        | ==> 	mutex_enter(block_mutex);
|        | ==> 	++block->page.buf_fix_count;
|        | ==> 	mutex_exit(block_mutex);
|    | ==> rw_lock_s_unlock(hash_lock);
|    | ==> buf_wait_for_read(fix_block);

プロセスは次のとおりです.
  • ペアPage_Hashにsロックをかけて、存在するかどうかを判断します.
  • が存在しない場合、sロックを解放し、bpの反発ロック、xロックを加える.存在するか否かを再判断する.
  • が存在しない場合、xロックを解放し、空きBlockを申請する.
  • それからxロックをかけて、存在するかどうかを判断して、存在しないならば、空きBLockを挿入します.xロック
  • を解放する
  • blockをlruチェーンテーブルに追加します.bpの反発ロックを解除します.

  • ステップ3でxロックを解放するのは、スレッドがbpの反発ロックを有し、lrufreelistの操作が反発ロックに依存するためである.従って、bpの反発ロックによって、他のスレッドが空きBlockを申請することをブロックすることができる.しかし、LruからBLockを申請する過程で、スリープ待ちのために反発ロックを解放する必要があり、他のスレッドが入る可能性があるため、第4ステップは、空きBLockのソースに基づいて再チェックが必要かどうかを判断する.
    ディスク読み出し中にhashに対する反発コストが比較的高く,xロックが2回加算されていることがわかる.この場所の後続バージョンには最適化があります.
    Pageメモリ読み出しとPage淘汰の反発
    buf_flush_batch
    |    | ==> // LRU LOCK
    |    | ==> buf_pool_mutex_enter(buf_pool);
    |    | ==> count = buf_do_LRU_batch(buf_pool, min_n);
    |        | ==> buf_flush_LRU_list_batch(buf_pool, max - count);
    |            | ==> bpage = UT_LIST_GET_LAST(buf_pool->LRU);
    |            | ==> mutex_enter(block_mutex);
    |            | ==> evict = buf_flush_ready_for_replace(bpage);
    |                | ==> bpage->buf_fix_count == 0
    |            | ==> mutex_exit(block_mutex);
    |            | ==> if (evict) buf_LRU_free_page
    |                | ==> rw_lock_x_lock(hash_lock);
    |                | ==> mutex_enter(block_mutex);
    |                | ==> //        
    |                | ==> buf_page_can_relocate
    |                | ==> // LRU HASH   
    |                | ==> buf_LRU_block_remove_hashed
    |                    | ==> buf_LRU_remove_block(bpage);
    |                    | ==> HASH_DELETE(buf_page_t, hash, buf_pool->page_hash, fold, bpage);
    |                    | ==> rw_lock_x_unlock(hash_lock);
    |                | ==> buf_pool_mutex_exit(buf_pool);
    |                | ==> buf_pool_mutex_enter(buf_pool);
    |                | ==> buf_LRU_block_free_hashed_page((buf_block_t*) bpage);
    |                    | ==> buf_LRU_block_free_non_file_page(block);
    |                        | ==> UT_LIST_ADD_FIRST(list, buf_pool->free, (&block->page));
    |    | ==> buf_pool_mutex_exit(buf_pool);
    

    Pageの淘汰過程は以下の通りである.
  • BPの反発ロック
  • LRUチェーンテーブルから最も古いデータページ
  • を取得する.
  • Pageが淘汰できるかどうかを確認する
  • .
  • もし淘汰できるならば、hashをプラスしますPageのxロック、このとき再判断、前述の判断でPageへのアクセスをブロックできないため、このときPage_hashにxロックをかけて、正確な判断を行います.
  • 確実に淘汰できればPageからHashで削除し、hashのxロックを解除します.
  • Pageをアイドルチェーンテーブル
  • に加える.