博客园  :: 首页  :: 新随笔  :: 订阅 订阅  :: 管理

MySQL源码解读之数据结构-动态数组

Posted on 2021-07-02 16:37  面具下的戏命师  阅读(301)  评论(0编辑  收藏  举报

MySQL源码解读之数据结构-动态数组

有时候在使用数组时,不能确定数组的大小。遇到这种情况在声明数组时,如果长度过小在使用时会导致数组溢出,长度过长会造成内存空间的浪费。因此动态数组的出现就是为了解决这个问题,在声明数组时不指定大小,在运行时具有可以改变数组大小的能力。

在MySQL中,自身定义了许多数据结构。存放在源码的mysys目录,源码中通过这些数据结构来组织数据,更容易实现跨平台。

源码解读

先来看一眼MySQL源码中动态数组的定义:

[源码路径:include/my_sys.h, mysys/array.cc]

struct DYNAMIC_ARRAY {
  uchar *buffer{nullptr};
  uint elements{0}, max_element{0};
  uint alloc_increment{0};
  uint size_of_element{0};
  PSI_memory_key m_psi_key{PSI_NOT_INSTRUMENTED};
};

可以看到,DYNAMIC_ARRAY是一个结构体。每个元素的解释如下:

  • uchar *buffer{nullptr}           定义一个uchar类型的指针,指向动态数组。
  • uint elements{0}                  数组中元素的个数,默认值为0
  • uint max_element{0}            数组的总长度
  • uint alloc_increment {0}       当数组元素写满数组时,自动扩展的长度
  • uint size_of_element{0}        数组中单个元素的大小(size_of)
  • PSI_memory_key m_psi_key{PSI_NOT_INSTRUMENTED}    内存资源检测,宏定义PSI_NOT_INSTRUMENTED默认值为0,不打开检测

插话:PSI是用来评估系统资源压力的,CPU、内存、IO。参考博客:纯干货,PSI 原理解析与应用

接下来来看一下MySQL中对动态数组的操作函数:

1、my_init_dynamic_array 数组初始化

bool my_init_dynamic_array(DYNAMIC_ARRAY *array, PSI_memory_key psi_key,
                           uint element_size, void *init_buffer,
                           uint init_alloc, uint alloc_increment) 

函数介绍:

array  指向动态数组的指针

element_size  单个元素的大小(size_of)

init_buffer    初始缓冲区指针

init_alloc     初始元素个数,如果传入为0,则init_alloc = alloc_increment。

alloc_increment   添加新元素时,数组扩展的增量大小。如果传入为0,会根据元素大小进行计算,计算方法自行查看代码

如果初始化内存分配失败,那么这个数据也是可用的。所以这个函数的返回值永远是 false,也就是OK的状态。

2、insert_dynamic 插入一个元素

bool insert_dynamic(DYNAMIC_ARRAY *array, const void *element)

函数介绍:

array 指向动态数组的指针

element  将被插入的元素

如果elements==max_element,则内存空间已经使用完,需要调用alloc_dynamic函数realloc空间。内存重新分配成功或者内存空间没用完,直接在当前数组的最后插入元素。

3、 alloc_dynamic 为下一个元素分配内存空间

void *alloc_dynamic(DYNAMIC_ARRAY *array)

函数介绍:

分配新的元素空间,内存空间已经使用完,需要realloc空间,并把原来空间的内存memcpy过来。

4、delete_dynamic 删除动态数组

void delete_dynamic(DYNAMIC_ARRAY *array)

函数介绍:

删除动态数组,释放内存。