现在位置:中国IDC吧>数据库>SQL server数据库> 文章内容

MySQL内核:innodb动态数组内部实现

收藏发布 来源:IT专家网 作者:中国IDC吧 更新日期:2008-09-30 点击:
  动态数组涉及的文件是innodb存储引擎的三个文件:dyn0dyn.h、dyn0dyn.ic以及dyn0dyn.c。这是一个基本的组件功能,是作为一个动态的虚拟线性数组。本文对innodb动态数组内部实现做了详细介绍。

  1. 动态数组概述

  动态数组涉及的文件是innodb存储引擎的三个文件:dyn0dyn.h、dyn0dyn.ic以及dyn0dyn.c。

  这是一个基本的组件功能,是作为一个动态的虚拟线性数组。数组的基本元素是byte。动态数组dyn主要用来存放mtr的锁定信息以及log。Dyn在实现上,如果block需要分裂节点,则会使用一个内存堆。每个blok块存储数据的数据字段的长度是固定的(默认值是512),但是不一定会完全用完。假设需要存储的数据项的尺寸大于数据块时,该数据项被分拆,这种情况主要用于log的缓冲。

  2. 数据结构

 

typedef struct dyn_block_struct dyn_block_t;
typedef dyn_block_t dyn_array_t;
#defineDYN_ARRAY_DATA_SIZE 512

struct dyn_block_struct{
mem_heap_t* heap;
ulint used;
byte data[DYN_ARRAY_DATA_SIZE];
UT_LIST_BASE_NODE_T(dyn_block_t) base;
UT_LIST_NODE_T(dyn_block_t) list;
#ifdef UNIV_DEBUG
ulint buf_end;
ulint magic_n;
#endif
};

//下面两个是公 1 2 3 4 5 6 :   动态数组涉及的文件是innodb存储引擎的三个文件:dyn0dyn.h、dyn0dyn.ic以及dyn0dyn.c。这是一个基本的组件功能,是作为一个动态的虚拟线性数组。本文对innodb动态数组内部实现做了详细介绍。

 

UNIV_INLINE
dyn_array_t*
dyn_array_create(
/*=============*/
/* out: initialized dyn array */
dyn_array_t*arr)/* in: pointer to a memory buffer of
size sizeof(dyn_array_t) */
{
ut_ad(arr);
ut_ad(DYN_ARRAY_DATA_SIZE < DYN_BLOCK_FULL_FLAG);

arr->heap = NULL;
arr->used = 0;

#ifdef UNIV_DEBUG
arr->buf_end = 0;
arr->magic_n = DYN_BLOCK_MAGIC_N;
#endif
return(arr);
}

 

  其中的ud_ad是属于红判断,相当于assert。这个我们暂时不表。这个函数是在mtr创建的时候来调用的,在调用的时候已经分配了arr指针。

  在dyn_array_create函数中,系统将heap字段设置为NULL,Used设置为0。Buf_end和magic_n是调试的时候使用的,每个结构体定义都会唯一的对应一个magic_n值。这样在调试的时候,就可以快速进行问题的跟踪。

  下面一个问题是,既然heap在起初的设置为NULL,那么什么时候分配给它值?是第一次分配block成员的时候?还是每次分配block成员的时候?

  我们这里暂不分析如何插入,我们先看看,当dyn数组已经数据不够用的时候,我们怎么给这个arr增加一个新的block。代码如下:

 

dyn_block_t*
dyn_array_add_block(
/*================*/
/* out: created block */
dyn_array_t*arr)/* in: dyn array */
{
mem_heap_t*heap;
dyn_block_t*block;

ut_ad(arr);
ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N);

if (arr->heap == NULL) {
UT_LIST_INIT(arr->base);
UT_LIST_ADD_FIRST(list, arr->base, arr);

arr->heap = mem_heap_create(sizeof(dyn_block_t));
}

block = dyn_array_get_last_block(arr);
block->used = block->used | DYN_BLOCK_FULL_FLAG;

heap = arr->heap;

block = mem_heap_alloc(heap, sizeof(dyn_block_t));

block->used = 0;

UT_LIST_ADD_LAST(list, arr->base, block);

return(block);
}

 

  代码中,我们可以看出,第一次增加block的时候,因为“arr->heap == NULL”条件为真,就会创建一个heap堆,在以后的再增加block时,就会使用的该堆直接分配。所以,我们可以得知,对于dyn动态数组,只有首节点的heap才是有效的。 9 1 2 3 4 5 6 7 :   动态数组涉及的文件是innodb存储引擎的三个文件:dyn0dyn.h、dyn0dyn.ic以及dyn0dyn.c。这是一个基本的组件功能,是作为一个动态的虚拟线性数组。本文对innodb动态数组内部实现做了详细介绍。

  好,那我们通过图形来看下,增加新节点之后的图形变化。

Mysql内核

  图1表示的是只有一个节点时的情况,当节点分裂时的变化,见图2。

Mysql内核

  通过图2,并集合前面的代码,我们可以发现,从第一个节点,变为两个节点的时候,首节点先把自己挂到base链表中,并分配一个新的节点,挂在base的最后一个节点。链表中的节点通过list进行互连。同样,如果还需要再增加一个节点,那么就在base链表的结尾再增加一个。因为是新增节点,所以设置该节点的used值为0。

  我们在关注一下这一行代码:

  block->used = block->used | DYN_BLOCK_FULL_FLAG;

  从这一行代码,我们可以猜想一下该行代码的含义: 9 1 2 3 4 5 6 7 :   动态数组涉及的文件是innodb存储引擎的三个文件:dyn0dyn.h、dyn0dyn.ic以及dyn0dyn.c。这是一个基本的组件功能,是作为一个动态的虚拟线性数组。本文对innodb动态数组内部实现做了详细介绍。

  a) FULL表明该节点已经完全使用完,不可以再使用其中的空间。所以,链表只有最后一个节点才是可以使用的。每增加一个节点,总要设置前面一个节点的DYN_BLOCK_FULL_FLAG。

  b) 每个块,data数组的预设值是DYN_ARRAY_DATA_SIZE(值为512),

上一页12 3 下一页
收藏此页到网摘/书签:
所有评论

评论列表

用户名: 新注册) 密码: 匿名评论