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)
函数介绍:
删除动态数组,释放内存。