ImageVerifierCode 换一换
格式:DOCX , 页数:13 ,大小:138.98KB ,
资源ID:16593164      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/16593164.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(思考mysql内核之初级系列9innodb动态数组的实现Word下载.docx)为本站会员(b****4)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

思考mysql内核之初级系列9innodb动态数组的实现Word下载.docx

1、 /* MTR_ACTIVE, MTR_COMMITTING, MTR_COMMITTED */ dyn_array_t memo; /* memo stack for locks etc. */ dyn_array_t log; /* mini-transaction log */ ibool modifications; /* TRUE if the mtr made modifications to buffer pool pages */ ulint n_log_recs; /* count of how many page initial log records have been

2、written to the mtr log */ ulint log_mode; /* specifies which operations should be logged; default value MTR_LOG_ALL */ dulint start_lsn;/* start lsn of the possible log entry for this mtr */ dulint end_lsn;/* end lsn of the possible log entry for ulint magic_n; 我们将要开始fsp0fsp.c的内容,为了便于内容的独立,会将mtr的内容先

3、剥离,在讲完存储之后,会继续讲B树,然后会到事务。” Bingxi:“alex,我赞同这一点。不过我认为还是把该结构体中的一个常用算法讲下,就是动态数组,mtr_t结构体中会有两个这样的结构成员:dyn_array_t memo;dyn_array_t log; 所谓动态数组,就是一个动态的虚拟线性数组,数组的基本元素是byte,主要用于存放mtr的锁信息以及log。如果对于一个block数组不够存放时,需要增加新的block,每个block对应的存放数据字段的长度是固定的(默认值是512),但是不一定会用完。假设已经用了500个字节,这时候需要继续存放18个字节的内容,就会在该块中存放不了,

4、会产生一个新的block用于存放。从而前一个block使用值为500。 我们先看了结构体的定义:typedef struct dyn_block_struct dyn_block_t;typedef dyn_block_t dyn_array_t;/*#*/* NOTE! Do not use the fields of the struct directly: the definitionappears here only for the compiler to know its size! */struct dyn_block_struct mem_heap_t* heap; /* in

5、the first block this is != NULL if dynamic allocation has been needed */ ulint used; /* number of data bytes used in this block */ byte dataDYN_ARRAY_DATA_SIZE; /* storage for array elements */ UT_LIST_BASE_NODE_T(dyn_block_t) base; /* linear list of dyn blocks: this node is used only in the first b

6、lock */ UT_LIST_NODE_T(dyn_block_t) list; /* linear list node: used in all blocks */#ifdef UNIV_DEBUG ulint buf_end;/* only in the debug version: if dyn array is opened, this is the buffer end offset, else this is 0 */#endif 在这个结构体中,我们可以看到上一篇聊到的list结构,可以通过list查找prev、next。 Alex,这里面就带来了一些问题:1) dyn_arr

7、ay_t与dyn_block_t是同样的定义,而一个动态数组只有一个首结点,那么UT_LIST_BASE_NODE_T(dyn_block_t) base成员是不是每个结构体都是有效的,2)一开始分配的时候只分配了一个结构体,也就是512字节的大小,如果不够用,则扩展了一个,插入到链表里面,链表成员是1个还是2个?3)使用的时候,如何判断一个block已经使用满了,比如前面我们说到一个情况:500个字节剩下了12个不够18个时候,产生了一个新的block,假设这时候要使用其中的10个字节,两个block都是符合,用哪个?如果用后一个,怎么标识前一个是满的。“你的问题太多了,呵呵。我们先放下问题

8、,看一下动态数组的初始化过程。这里面,我们还需要主意一点。虽然数据结构用的是同一个dyn_block_struct,但是我们称第一个节点为arr,表明这个是动态数据的头节点。其它的节点,我们称为block节点。现在开始进行debug,在 mtr0mtr.ic文件中的mtr_start函数体内设置断点,这里也是动态数组创建的唯一入口,设置断点进行调试。/*Starts a mini-transaction and creates a mini-transaction handleand a buffer in the memory buffer given by the caller. */mt

9、r_t*mtr_start(/*=*/ mtr buffer which also acts as the mtr handle */ memory buffer for the mtr buffer */ /会创建两个动态数组,在两个创建的任一个设置断点 dyn_array_create(&(mtr-memo);log); mtr-log_mode = MTR_LOG_ALL;modifications = FALSE;n_log_recs = 0;state = MTR_ACTIVE;magic_n = MTR_MAGIC_N; return(mtr); 点击F11进入函数,查看动态数据的

10、创建过程:/*Initializes a dynamic array. */dyn_array_t*dyn_array_create(/*=*/ 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 heap = NULL;used = 0;buf_end = 0;magic_n = DYN_BLOCK_MAGIC_N; return(arr); 执行该函数之

11、后,结构体的情况见图1: 创建完成之后,我们就可以使用该动态数组了。作为例子,我们在mtr_memo_push函数体内设置断点。/*Pushes an object to an mtr memo stack. */voidmtr_memo_push(/*=*/ mtr_t* mtr, /* in: void* object, /* in: object */ ulint type) /* in: object type: MTR_MEMO_S_LOCK, . */ dyn_array_t* memo; mtr_memo_slot_t* slot; ut_ad(object); ut_ad(ty

12、pe = MTR_MEMO_PAGE_S_FIX); ut_ad(type magic_n = MTR_MAGIC_N); memo = &memo);/从动态中分配大小为sizeof(mtr_memo_slot_t)的空间/然后对获取的空间进行赋值 slot = dyn_array_push(memo, sizeof(mtr_memo_slot_t); slot-object = object;type = type; 从中我们可以得知dyn_array_pus是分配空间的地方(dyn_array_open函数有这样的功能,本文后面会提到),我们按F11进入该函数体。Makes room o

13、n top of a dyn array and returns a pointer to the added element.The caller must copy the element to the pointer returned. */void*dyn_array_push(/*=*/ pointer to the element */ dyn_array_t* arr, /* in: dynamic array */ ulint size) /* in: size in bytes of the element */ dyn_block_t* block; ut_ad(arr-m

14、agic_n = DYN_BLOCK_MAGIC_N); ut_ad(size used;/步骤2:如果首结点block有足够的空间存储,则返回指针,并修改used值。这种情况只出现在:该动态数组只有一个节点。/ used + size DYN_ARRAY_DATA_SIZE) /* Get the last array block */ /步骤3:首结点没有空间存储,则取得base列表的最后一个结点 /该函数等价于:block =UT_LIST_GET_LAST(arr-base); /如果有多个节点,首先肯定不符合used + size used = used + size; ut_ad(

15、block-used data) + used); 该函数的功能就是进行分配空间,如果有足够的空间则分配,否则就调用函数dyn_array_add_block生成一个新的block。假象现在的情形是一个block扩展为两个block的情况。查看该函数的实现。/*Adds a new block to a dyn array. */dyn_block_t*dyn_array_add_block(/*=*/ created block */ dyn array */结点是1扩展为2,还是n扩展为 n+1(n=2)/ arr-heap=NULL则是1扩展为 2,将自己作为首结点放在链表上,并分配一个

16、内存堆 if (arr-heap = NULL) UT_LIST_INIT(arr- UT_LIST_ADD_FIRST(list, arr-base, arr); /1扩展为 2的时候,创建一个heap,n扩展 n+1(n=2)时,则使用该heapheap = mem_heap_create(sizeof(dyn_block_t); 取得最后一个结点,将该block的used字段进行DYN_BLOCK_FULL_FLAG与操作,表示该结点已经使用满。每增加一个新的block总要将前一个block设置为已满,因此只有最后一个block是可用的。即使如前文所例,500字节不够用时创建了一个新的b

17、lock,第二次有申请10个字节时,显示显示该块的大小512了,因为DYN_BLOCK_FULL_FLAG的值为:0x1000000ULused = block-used | DYN_BLOCK_FULL_FLAG; heap = arr-heap;创建一个新结点,并插入到链表尾 block = mem_heap_alloc(heap, sizeof(dyn_block_t); UT_LIST_ADD_LAST(list, arr-base, block); return(block); 1个结点扩展为2个结点后,见图2(prev和next指向结构的首字节,便于绘图进行了简化,此处加以说明。l

18、ist的prev和next参考前一篇文章): 2个结点扩展为3个结点,见图3: 到这里,我们就解决了前面的三个问题。问题1:dyn_array_t与dyn_block_t是同样的定义,而一个动态数组只有一个首结点,那么UT_LIST_BASE_NODE_T(dyn_block_t) base成员是不是每个结构体都是有效的?“这个问题我明白,只有首结点的base是有效的。从图1中可以看出,只有一个结点时,base是无效。图2中,arr的base有两个成员,首结点是第一个成员,新增加的结点在首结点的后面。图3中,arr的base有三个成员,新增的成员在链表尾。” “问题2:一开始分配的时候只分配了

19、一个结构体,也就是512字节的大小,如果不够用,则扩展了一个,插入到链表里面,链表成员是1个还是2个?“从1个扩展到2个,链表的成员是2。“问题3:使用的时候,如何判断一个block已经使用满了,比如前面我们说到一个情况:“始终只有最后一个结点可能被使用,只有一个成员时,本身就是最后一个结点。新增结点时,会将前一个结点设置为已满。设置方法如下:block- 这样进行分配操作时候,used + size DYN_ARRAY_DATA_SIZE这个条件一定为真。表示首结点已经用满了,然后取最后一个结点。该条件只有一种情况为否,就是动态数组只有一个成员。if (used + size “good,我现在问第4个问题:我们需要插入三个元素,我们插入一个元素,就需要修改一次used,再插入,又得调用push函数进行操作。频繁的对dyn的数据结构进行操作。这样的效率是很低的。“稍等,我看下代码。找到了,通过dyn_array_open、dyn_array_close函数可以解决这个问题。这两个函数建议大家看下。另外,我也问你第5个问题,是不是大于512字节的数据就不能插入?“这个问题,请参考函数dyn_push_string。其它的函数也看一下,养成看函数的习惯,呵呵。今天就到这儿吧。“ok”

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1