在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.&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>&nbsp;&nbsp;&nbsp;&nbsp;``const</code> <code>rec_t*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rec,&nbsp;&nbsp;&nbsp; ``/*!&lt; in: physical record */</code>
<code>&nbsp;&nbsp;&nbsp;&nbsp;``const</code> <code>dict_index_t* index,&nbsp; ``/*!&lt; in: record descriptor */</code>
<code>&nbsp;&nbsp;&nbsp;&nbsp;``ulint*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; offsets,``/*!&lt; in/out: array consisting of</code>
<code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;``offsets[0] allocated elements,</code>
<code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;``or an array from rec_get_offsets(),</code>
<code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;``or null */</code>
<code>&nbsp;&nbsp;&nbsp;&nbsp;``ulint&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; n_fields,``/*!&lt; in: maximum number of</code>
<code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;``initialized fields</code>
<code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;``(ulint_undefined if all fields) */</code>
<code>&nbsp;&nbsp;&nbsp;&nbsp;``mem_heap_t**&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; heap,&nbsp;&nbsp; ``/*!&lt; in/out: memory heap */</code>
<code>&nbsp;&nbsp;&nbsp;&nbsp;``const</code> <code>char``*&nbsp;&nbsp;&nbsp;&nbsp; file,&nbsp;&nbsp; ``/*!&lt; in: file name where called */</code>
<code>&nbsp;&nbsp;&nbsp;&nbsp;``ulint&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; line);&nbsp; ``/*!&lt; in: line number where called */</code>
<code>#define rec_get_offsets(rec,index,offsets,n,heap)&nbsp;&nbsp;</code>
<code>&nbsp;&nbsp;&nbsp;&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&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; offsets_[rec_offs_normal_size];</code>
<code>&nbsp;``ulint*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; offsets&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = offsets_;</code>
<code>&nbsp;``mem_heap_t* heap&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = null;</code>
<code>&nbsp;``row_cache_chain_t* chain = null;</code>
<code>&nbsp;``rec_offs_init(offsets_);</code>
<code>//todo someting</code>
<code>&nbsp;``if</code> <code>(univ_likely_null(heap)) {</code>
<code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;``mem_heap_free(heap);</code>
<code>&nbsp;``}</code>
<code>&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>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;``mem_heap_free(heap);</code>
<code>&nbsp;&nbsp;&nbsp;&nbsp;``}</code>
這一段了,一旦漏了,就很有可能出現記憶體洩露,而且這個洩露的觸發條件還很苛刻,因為初始化的offsets_[rec_offs_normal_size]為100個,那麼當你有超過96個字段的記錄(因為内部要預留4個)時,就會向heap申請記憶體,這時沒有free就會洩露了.
本文來源于"阿裡中間件團隊播客",原文發表時間" 2011-09-10 "