Innodb 中 rec_get_offsets 的使用注意点

简介:
在Innodb中使用rec_get_offsets来获取一条rec_t的各个字段的偏移量

整个rec_get_offsets的形式为:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/******************************************************/``/**
The following function determines the offsets to each field
in the record.  It can reuse a previously allocated array.
@return the new offsets */
UNIV_INTERN
ulint*
rec_get_offsets_func(
/*=================*/
    ``const rec_t*        rec,    ``/*!< in: physical record */
    ``const dict_index_t* index,  ``/*!< in: record descriptor */
    ``ulint*          offsets,``/*!< in/out: array consisting of
                    ``offsets[0] allocated elements,
                    ``or an array from rec_get_offsets(),
                    ``or NULL */
    ``ulint           n_fields,``/*!< in: maximum number of
                    ``initialized fields
                     ``(ULINT_UNDEFINED if all fields) */
    ``mem_heap_t**        heap,   ``/*!< in/out: memory heap */
    ``const char``*     file,   ``/*!< in: file name where called */
    ``ulint           line);  ``/*!< in: line number where called */
 
#define rec_get_offsets(rec,index,offsets,n,heap)  
    ``rec_get_offsets_func(rec,index,offsets,n,heap,__FILE__,__LINE__)

参数解释:

  • rec  对应的记录
  • index 记录对应的索引
  • offsets 用来保存偏移量结果的指针,可以是预分配好的,也可以是个NULL
  • n_fields 能保存的最大的偏移量的字段数 一般可以使用ULINT_UNDEFINED来表示,没限制.ULINT_UNDEFINED 为((ulint)(-1))
  • heap 内存堆.如果没有预先分配offsets ,那么返回结果将在heap上申请内存,如果heap为NULL,那么会为heap也申请内存.注意.这个地方很容易引起内存泄露

看上对offsets 和 heap的使用要注意了,一个不当就是引起内存泄露

看一个标准用法:

?
1
2
3
4
5
6
7
8
9
10
ulint       offsets_[REC_OFFS_NORMAL_SIZE];
 ``ulint*      offsets             = offsets_;
 ``mem_heap_t* heap                = NULL;
 ``row_cache_chain_t* chain = NULL;
 ``rec_offs_init(offsets_);
//TODO Someting
 ``if (UNIV_LIKELY_NULL(heap)) {
     ``mem_heap_free(heap);
 ``}
 ``return``;

第一个需要注意的就是rec_offsinit(offsets); 这句不能省,这个宏的目的是设置offset_的第一个数组单位的值为数值的大小,因为rec_get_offsets内部需要判断offset能不能放下所有的值,放不下的话需要向heap申请内存,怎么判断offset够不够用,就需要rec_offsinit(offsets);来初始化大小

上面这个例子里面使用的heap是为NULL的,即外部不预先为heap申请内存,难么当offset不够用时,rec_get_offsets内部会主动在heap上申请内存了.这个时候有个注意点就是rec_get_offsets内只在heap上申请了内存并没有free,因为外面还要使用,那么不能漏的就是

?
1
2
3
if (UNIV_LIKELY_NULL(heap)) {
        ``mem_heap_free(heap);
    ``}

这一段了,一旦漏了,就很有可能出现内存泄露,而且这个泄露的触发条件还很苛刻,因为初始化的offsets_[REC_OFFS_NORMAL_SIZE]为100个,那么当你有超过96个字段的记录(因为内部要预留4个)时,就会向heap申请内存,这时没有free就会泄露了.

本文来源于"阿里中间件团队播客",原文发表时间" 2011-09-10 "

相关文章
|
6月前
|
存储 缓存 算法
InnoDB的Buffer Pool
InnoDB的Buffer Pool
59 3
|
存储 缓存 关系型数据库
InnoDB的特点
InnoDB是MySQL数据库的存储引擎之一
146 0
|
26天前
|
存储 缓存 关系型数据库
什么是InnoDB
【10月更文挑战第17天】什么是InnoDB
|
5月前
|
缓存 关系型数据库 MySQL
MySQL数据库——InnoDB引擎-架构-内存结构(Buffer Pool、Change Buffer、Adaptive Hash Index、Log Buffer)
MySQL数据库——InnoDB引擎-架构-内存结构(Buffer Pool、Change Buffer、Adaptive Hash Index、Log Buffer)
98 3
|
6月前
|
存储 监控 关系型数据库
InnoDB
【5月更文挑战第14天】InnoDB
52 3
|
存储 SQL 缓存
InnoDB之UNDO LOG介绍
undo log是InnoDB事务特性的重要组成部分。当对记录做增删改操作就会产生undo记录,undo记录会记录到单独的表空间中。 本文将从代码层面对undo log进行一个简单的介绍;主要从下面四个方面来介绍undo log:undo log组织形式与分配与记录,以及undo log的应用及其清理。从这四个方面出发,我们就可以基本了解undo log的整个生命周期。
717 1
|
存储 SQL 关系型数据库
有了InnoDB,Memory存储引擎还有意义吗?(上)
两个group by 语句都用了order by null,为什么使用内存临时表得到的语句结果里,0这个值在最后一行;而使用磁盘临时表得到的结果里,0这个值在第一行?
123 0
有了InnoDB,Memory存储引擎还有意义吗?(上)
|
存储 关系型数据库 MySQL
有了InnoDB,Memory存储引擎还有意义吗?(下)
两个group by 语句都用了order by null,为什么使用内存临时表得到的语句结果里,0这个值在最后一行;而使用磁盘临时表得到的结果里,0这个值在第一行?
148 0
有了InnoDB,Memory存储引擎还有意义吗?(下)
|
存储 关系型数据库 MySQL
InnoDB限制
InnoDB 限制 Limits MySQL
437 0
|
关系型数据库 MySQL
Consistent Nonlocking Reads,Locking Reads 和Phantom Rows
以Consistent Nonlocking Reads,Locking Reads为突破点,用简单的例子来说明mysql常用的事务隔离级别(READ COMMITTED, REPEATABLE READ)和lock(record lock,gap lock,next-key lock, Insert Intention Lock)的关系
Consistent Nonlocking Reads,Locking Reads 和Phantom Rows