Data structure of MySQL source code interpretation - LF_HASH

Posted by brandondrury on Fri, 14 Jan 2022 12:31:08 +0100

Data structure of MySQL source code interpretation - LF_HASH

MySQL implements a Lock Free hash structure called LF in the code_ Hash. Metadata_Lock depends on it. LF_ Hash has the following characteristics:

1. Dynamic expansion:

The number of buckets during initialization is 1 Each bucket has one element on average. Therefore, when the total number of elements exceeds the number of buckets, it will be automatically split. Double the number of buckets per split

2,Lock Free

lf_hash is implemented in Lock Free mode to ensure the safety of multithreading operation. lf_hash implements something called pin to ensure the security of multithreaded operation. lf_ All hash operations need to be protected by pins. So lf_hash provides functions to get and release pins. lf_hash maintains a dynamic array of pins.

3. Memory management

lf_ The memory of the hash element is lf_hash allocation and management. The user's data needs to be copied to LF_ In the element created by hash.

LF_ Basic structure of hash

lf_ The basic structure of hash has the following characteristics: all elements are maintained in a global sorting linked list, and all elements of the same bucket are arranged together. As shown in the figure below:

 

Element management

lf_ The element of the hash uses a continuous memory, which contains two parts of information:

  • LF_SLIST linked list and hash related information
  • User data is placed in LF_ After slist.

LF_SLIST

struct LF_SLIST {
  std::atomic<LF_SLIST *>
      link;      /* a pointer to the next element in a listand a flag */
  uint32 hashnr; /* reversed hash number, for sorting                 */
  const uchar *key;
  size_t keylen;
  /*
    data is stored here, directly after the keylen.
    thus the pointer to data is (void*)(slist_element_ptr+1)
  */
};
  • link: points to the next element in the linked list
  • Hashnr: reverse value of hash
  • Key: the pointer points to the key value
  • keylen: the length of the key

LF_HASH

struct LF_HASH {
  LF_DYNARRAY array;             /* hash itself */
  LF_ALLOCATOR alloc;            /* allocator for elements */
  hash_get_key_function get_key; /* see HASH */
  CHARSET_INFO *charset;         /* see HASH */
  lf_hash_func *hash_function;   /* see HASH */
  uint key_offset, key_length;   /* see HASH */
  uint element_size;             /* size of memcpy'ed area on insert */
  uint flags;                    /* LF_HASH_UNIQUE, etc */
  std::atomic<int32> size;       /* size of array */
  std::atomic<int32> count;      /* number of elements in the hash */
  /**
    "Initialize" hook - called to finish initialization of object provided by
     LF_ALLOCATOR (which is pointed by "dst" parameter) and set element key
     from object passed as parameter to lf_hash_insert (pointed by "src"
     parameter). Allows to use LF_HASH with objects which are not "trivially
     copyable".
     NULL value means that element initialization is carried out by copying
     first element_size bytes from object which provided as parameter to
     lf_hash_insert.
  */
  lf_hash_init_func *initialize;
};

Array = dynamic array. All elements of hash are stored in the dynamic array.  

alloc memory allocator, which requests memory space for hash elements

get_key , used to retrieve from LF_ Extract the key and key length from user data in hash

charset - the character set used to calculate the hash value

hash_function function to calculate hash value

key_offset = the offset of the key after the user data to the hash

key_length - the length of the key after the hash

element_size size of user data

flags

Size - the size of the array (the number of bucket s)

count counts the number of elements in the hash table

Initialize is used to initialize an object. When the incoming user data is not replicable, you can pass in the initialization function for initialization. When initialize is null, the user data will be copied (memcopy).

 

CURSOR

typedef struct {
  std::atomic<LF_SLIST *> *prev;
  LF_SLIST *curr, *next;
} CURSOR;

Function introduction:

1,lf_hash_init2 initialize lf_hash.

2,LF_HASH_ Destroy LF_HASH,. .

3,lf_hash_insert inserts a new element into the hash table. It will copy the hashed user data instead of a pointer to the user data. Return value 0 failed to insert into memory 1, unique key conflict - 1 memory overflow

4,hash_key returns the pointer of the hash key and obtains the length of the hash key.

5,calc_hash} calculate hash value