MySQL InnoDB Engine--自适应哈希索引代码瞎猜01

1、自适应哈希索引初始化

在storage\innobase\buf\buf0buf.cc的函数buf_pool_init负责初始化Buffer pool, 会调用btr_search_sys_create来初始化AHI,并分配当前Buffer pool内存的1/64给AHI。

/** Creates the buffer pool.
@param[in]  total_size    Size of the total pool in bytes.
@param[in]  n_instances   Number of buffer pool instances to create.
@return DB_SUCCESS if success, DB_ERROR if not enough memory or error */
dberr_t buf_pool_init(ulint total_size, ulint n_instances) {
    
    /** 初始化AHI并分片buffer pool的1/64内存给AHI **/
    btr_search_sys_create(buf_pool_get_curr_size() / sizeof(void *) / 64);
}

在btr_search_sys_create中,会按照参数innodb_adaptive_hash_index_parts来设置hash_tabsles数量,并将内存平均分配给每个hash_table。

在创建每个hash_table时,会按照(hash_size / btr_ahi_parts)来设置hash_table的cells数量。

/** Creates and initializes the adaptive search system at a database start.
@param[in]    hash_size    hash table size. */
void btr_search_sys_create(ulint hash_size) {
  /* Search System is divided into n parts.
  Each part controls access to distinct set of hash buckets from
  hash table through its own latch. */

  /* Step-1: Allocate latches (1 per part). */
  btr_search_latches = reinterpret_cast<rw_lock_t **>(
      ut_malloc(sizeof(rw_lock_t *) * btr_ahi_parts, mem_key_ahi));

  for (ulint i = 0; i < btr_ahi_parts; ++i) {
    btr_search_latches[i] = reinterpret_cast<rw_lock_t *>(
        ut_malloc(sizeof(rw_lock_t), mem_key_ahi));

    rw_lock_create(btr_search_latch_key, btr_search_latches[i],
                   SYNC_SEARCH_SYS);
  }

  /* Step-2: Allocate hash tablees. */
  btr_search_sys = reinterpret_cast<btr_search_sys_t *>(
      ut_malloc(sizeof(btr_search_sys_t), mem_key_ahi));

  btr_search_sys->hash_tables = reinterpret_cast<hash_table_t **>(
      ut_malloc(sizeof(hash_table_t *) * btr_ahi_parts, mem_key_ahi));

  for (ulint i = 0; i < btr_ahi_parts; ++i) {
    btr_search_sys->hash_tables[i] =
        ib_create((hash_size / btr_ahi_parts), LATCH_ID_HASH_TABLE_MUTEX, 0,
                  MEM_HEAP_FOR_BTR_SEARCH);

#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
    btr_search_sys->hash_tables[i]->adaptive = TRUE;
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
  }
}

通过调用通用的ib_create函数来创建hast_table:

/** Creates a hash table with at least n array cells.  The actual number
 of cells is chosen to be a prime number slightly bigger than n.
 @return own: created table */
hash_table_t *ib_create(ulint n,       /*!< in: number of array cells */
                        latch_id_t id, /*!< in: latch ID */
                        ulint n_sync_obj,
                        /*!< in: number of mutexes to protect the
                        hash table: must be a power of 2, or 0 */
                        ulint type) /*!< in: type of datastructure for which
                                    MEM_HEAP_FOR_PAGE_HASH */
{
  hash_table_t *table;

  ut_a(type == MEM_HEAP_FOR_BTR_SEARCH || type == MEM_HEAP_FOR_PAGE_HASH);

  ut_ad(ut_is_2pow(n_sync_obj));
  table = hash_create(n);

  /* Creating MEM_HEAP_BTR_SEARCH type heaps can potentially fail,
  but in practise it never should in this case, hence the asserts. */

  if (n_sync_obj == 0) {
    table->heap = mem_heap_create_typed(
        ut_min(static_cast<ulint>(4096), MEM_MAX_ALLOC_IN_BUF / 2 -
                                             MEM_BLOCK_HEADER_SIZE -
                                             MEM_SPACE_NEEDED(0)),
        type);
    ut_a(table->heap);

    return (table);
  }

  if (type == MEM_HEAP_FOR_PAGE_HASH) {
    /* We create a hash table protected by rw_locks for
    buf_pool->page_hash. */
    hash_create_sync_obj(table, HASH_TABLE_SYNC_RW_LOCK, id, n_sync_obj);
  } else {
    hash_create_sync_obj(table, HASH_TABLE_SYNC_MUTEX, id, n_sync_obj);
  }

  table->heaps =
      static_cast<mem_heap_t **>(ut_malloc_nokey(n_sync_obj * sizeof(void *)));

  for (ulint i = 0; i < n_sync_obj; i++) {
    table->heaps[i] = mem_heap_create_typed(
        ut_min(static_cast<ulint>(4096), MEM_MAX_ALLOC_IN_BUF / 2 -
                                             MEM_BLOCK_HEADER_SIZE -
                                             MEM_SPACE_NEEDED(0)),
        type);
    ut_a(table->heaps[i]);
  }

  return (table);
}

/** Creates a hash table with >= n array cells. The actual number
 of cells is chosen to be a prime number slightly bigger than n.
 @return own: created table */
hash_table_t *hash_create(ulint n); /*!< in: number of array cells */

/* Fix Bug #13859: symbol collision between imap/mysql */
#define hash_create hash0_create

在hash_create函数中会跟进传入的cell数量重新计算,取一个大于"传入cell数量"的最小素数。

/** Creates a hash table with >= n array cells. The actual number of cells is
 chosen to be a prime number slightly bigger than n.
 @return own: created table */
hash_table_t *hash_create(ulint n) /*!< in: number of array cells */
{
  hash_cell_t *array;
  ulint prime;
  hash_table_t *table;

  prime = ut_find_prime(n);

  table = static_cast<hash_table_t *>(ut_malloc_nokey(sizeof(hash_table_t)));

  array =
      static_cast<hash_cell_t *>(ut_malloc_nokey(sizeof(hash_cell_t) * prime));

  /* The default type of hash_table is HASH_TABLE_SYNC_NONE i.e.:
  the caller is responsible for access control to the table. */
  table->type = HASH_TABLE_SYNC_NONE;
  table->cells = array;
  table->n_cells = prime;
#ifndef UNIV_HOTBACKUP
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
  table->adaptive = FALSE;
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
  table->n_sync_obj = 0;
  table->sync_obj.mutexes = nullptr;
  table->heaps = nullptr;
#endif /* !UNIV_HOTBACKUP */
  table->heap = nullptr;
  ut_d(table->magic_n = HASH_TABLE_MAGIC_N);

  /* Initialize the cell array */
  hash_table_clear(table);

  return (table);
}

 

posted @ 2021-07-09 17:25  TeyGao  阅读(132)  评论(0编辑  收藏  举报