天天看點

Innodb 中 rec_get_offsets 的使用注意點

在innodb中使用rec_get_offsets來擷取一條rec_t的各個字段的偏移量

整個rec_get_offsets的形式為:

<a href="http://jm.taobao.org/2011/09/10/1112/#">?</a>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

<code>/******************************************************/``/**</code>

<code>the following function determines the offsets to each field</code>

<code>in the record.&amp;nbsp; it can reuse a previously allocated array.</code>

<code>@return the new offsets */</code>

<code>univ_intern</code>

<code>ulint*</code>

<code>rec_get_offsets_func(</code>

<code>/*=================*/</code>

<code>&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;``const</code> <code>rec_t*&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; rec,&amp;nbsp;&amp;nbsp;&amp;nbsp; ``/*!&amp;lt; in: physical record */</code>

<code>&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;``const</code> <code>dict_index_t* index,&amp;nbsp; ``/*!&amp;lt; in: record descriptor */</code>

<code>&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;``ulint*&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; offsets,``/*!&amp;lt; in/out: array consisting of</code>

<code>&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;``offsets[0] allocated elements,</code>

<code>&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;``or an array from rec_get_offsets(),</code>

<code>&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;``or null */</code>

<code>&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;``ulint&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; n_fields,``/*!&amp;lt; in: maximum number of</code>

<code>&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;``initialized fields</code>

<code>&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;``(ulint_undefined if all fields) */</code>

<code>&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;``mem_heap_t**&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; heap,&amp;nbsp;&amp;nbsp; ``/*!&amp;lt; in/out: memory heap */</code>

<code>&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;``const</code> <code>char``*&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; file,&amp;nbsp;&amp;nbsp; ``/*!&amp;lt; in: file name where called */</code>

<code>&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;``ulint&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; line);&amp;nbsp; ``/*!&amp;lt; in: line number where called */</code>

<code>#define rec_get_offsets(rec,index,offsets,n,heap)&amp;nbsp;&amp;nbsp;</code>

<code>&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;``rec_get_offsets_func(rec,index,offsets,n,heap,__file__,__line__)</code>

參數解釋:

rec  對應的記錄

index 記錄對應的索引

offsets 用來儲存偏移量結果的指針,可以是預配置設定好的,也可以是個null

n_fields 能儲存的最大的偏移量的字段數 一般可以使用ulint_undefined來表示,沒限制.ulint_undefined 為((ulint)(-1))

heap 記憶體堆.如果沒有預先配置設定offsets ,那麼傳回結果将在heap上申請記憶體,如果heap為null,那麼會為heap也申請記憶體.注意.這個地方很容易引起記憶體洩露

看上對offsets 和 heap的使用要注意了,一個不當就是引起記憶體洩露

看一個标準用法:

<code>ulint&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; offsets_[rec_offs_normal_size];</code>

<code>&amp;nbsp;``ulint*&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; offsets&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = offsets_;</code>

<code>&amp;nbsp;``mem_heap_t* heap&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = null;</code>

<code>&amp;nbsp;``row_cache_chain_t* chain = null;</code>

<code>&amp;nbsp;``rec_offs_init(offsets_);</code>

<code>//todo someting</code>

<code>&amp;nbsp;``if</code> <code>(univ_likely_null(heap)) {</code>

<code>&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;``mem_heap_free(heap);</code>

<code>&amp;nbsp;``}</code>

<code>&amp;nbsp;``return``;</code>

第一個需要注意的就是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,因為外面還要使用,那麼不能漏的就是

<code>if</code> <code>(univ_likely_null(heap)) {</code>

<code>&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;``mem_heap_free(heap);</code>

<code>&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;``}</code>

這一段了,一旦漏了,就很有可能出現記憶體洩露,而且這個洩露的觸發條件還很苛刻,因為初始化的offsets_[rec_offs_normal_size]為100個,那麼當你有超過96個字段的記錄(因為内部要預留4個)時,就會向heap申請記憶體,這時沒有free就會洩露了.

本文來源于"阿裡中間件團隊播客",原文發表時間" 2011-09-10  "

繼續閱讀