1
by brian
clean slate |
1 |
/******************************************************
|
2 |
Insert buffer
|
|
3 |
||
4 |
(c) 1997 Innobase Oy
|
|
5 |
||
6 |
Created 7/19/1997 Heikki Tuuri
|
|
7 |
*******************************************************/
|
|
8 |
||
9 |
#include "buf0lru.h" |
|
10 |
#include "page0page.h" |
|
11 |
||
12 |
extern ulint ibuf_flush_count; |
|
13 |
||
14 |
/* If this number is n, an index page must contain at least the page size
|
|
15 |
per n bytes of free space for ibuf to try to buffer inserts to this page.
|
|
16 |
If there is this much of free space, the corresponding bits are set in the
|
|
17 |
ibuf bitmap. */
|
|
18 |
#define IBUF_PAGE_SIZE_PER_FREE_SPACE 32
|
|
19 |
||
20 |
/* Insert buffer data struct for a single tablespace */
|
|
21 |
struct ibuf_data_struct{ |
|
22 |
ulint space; /* space id */ |
|
23 |
ulint seg_size;/* allocated pages if the file segment |
|
24 |
containing ibuf header and tree */
|
|
25 |
ulint size; /* size of the insert buffer tree in pages */ |
|
26 |
ibool empty; /* after an insert to the ibuf tree is |
|
27 |
performed, this is set to FALSE, and if a
|
|
28 |
contract operation finds the tree empty, this
|
|
29 |
is set to TRUE */
|
|
30 |
ulint free_list_len; |
|
31 |
/* length of the free list */
|
|
32 |
ulint height; /* tree height */ |
|
33 |
dict_index_t* index; /* insert buffer index */ |
|
34 |
UT_LIST_NODE_T(ibuf_data_t) data_list; |
|
35 |
/* list of ibuf data structs */
|
|
36 |
ulint n_inserts;/* number of inserts made to the insert |
|
37 |
buffer */
|
|
38 |
ulint n_merges;/* number of pages merged */ |
|
39 |
ulint n_merged_recs;/* number of records merged */ |
|
40 |
};
|
|
41 |
||
42 |
struct ibuf_struct{ |
|
43 |
ulint size; /* current size of the ibuf index |
|
44 |
trees in pages */
|
|
45 |
ulint max_size; /* recommended maximum size in pages |
|
46 |
for the ibuf index tree */
|
|
47 |
UT_LIST_BASE_NODE_T(ibuf_data_t) data_list; |
|
48 |
/* list of ibuf data structs for
|
|
49 |
each tablespace */
|
|
50 |
};
|
|
51 |
||
52 |
/****************************************************************************
|
|
53 |
Sets the free bit of the page in the ibuf bitmap. This is done in a separate
|
|
54 |
mini-transaction, hence this operation does not restrict further work to only
|
|
55 |
ibuf bitmap operations, which would result if the latch to the bitmap page
|
|
56 |
were kept. */
|
|
57 |
||
58 |
void
|
|
59 |
ibuf_set_free_bits( |
|
60 |
/*===============*/
|
|
61 |
ulint type, /* in: index type */ |
|
62 |
page_t* page, /* in: index page; free bit is reset if the index is |
|
63 |
a non-clustered non-unique, and page level is 0 */
|
|
64 |
ulint val, /* in: value to set: < 4 */ |
|
65 |
ulint max_val);/* in: ULINT_UNDEFINED or a maximum value which |
|
66 |
the bits must have before setting; this is for
|
|
67 |
debugging */
|
|
68 |
||
69 |
/**************************************************************************
|
|
70 |
A basic partial test if an insert to the insert buffer could be possible and
|
|
71 |
recommended. */
|
|
72 |
UNIV_INLINE
|
|
73 |
ibool
|
|
74 |
ibuf_should_try( |
|
75 |
/*============*/
|
|
76 |
dict_index_t* index, /* in: index where to insert */ |
|
77 |
ulint ignore_sec_unique) /* in: if != 0, we should |
|
78 |
ignore UNIQUE constraint on
|
|
79 |
a secondary index when we
|
|
80 |
decide */
|
|
81 |
{
|
|
82 |
if (!(index->type & DICT_CLUSTERED) |
|
83 |
&& (ignore_sec_unique || !(index->type & DICT_UNIQUE))) { |
|
84 |
||
85 |
ibuf_flush_count++; |
|
86 |
||
87 |
if (ibuf_flush_count % 8 == 0) { |
|
88 |
||
89 |
buf_LRU_try_free_flushed_blocks(); |
|
90 |
}
|
|
91 |
||
92 |
return(TRUE); |
|
93 |
}
|
|
94 |
||
95 |
return(FALSE); |
|
96 |
}
|
|
97 |
||
98 |
/***************************************************************************
|
|
99 |
Checks if a page address is an ibuf bitmap page address. */
|
|
100 |
UNIV_INLINE
|
|
101 |
ibool
|
|
102 |
ibuf_bitmap_page( |
|
103 |
/*=============*/
|
|
104 |
/* out: TRUE if a bitmap page */
|
|
105 |
ulint page_no)/* in: page number */ |
|
106 |
{
|
|
107 |
if (page_no % XDES_DESCRIBED_PER_PAGE == FSP_IBUF_BITMAP_OFFSET) { |
|
108 |
||
109 |
return(TRUE); |
|
110 |
}
|
|
111 |
||
112 |
return(FALSE); |
|
113 |
}
|
|
114 |
||
115 |
/*************************************************************************
|
|
116 |
Translates the free space on a page to a value in the ibuf bitmap.*/
|
|
117 |
UNIV_INLINE
|
|
118 |
ulint
|
|
119 |
ibuf_index_page_calc_free_bits( |
|
120 |
/*===========================*/
|
|
121 |
/* out: value for ibuf bitmap bits */
|
|
122 |
ulint max_ins_size) /* in: maximum insert size after reorganize |
|
123 |
for the page */
|
|
124 |
{
|
|
125 |
ulint n; |
|
126 |
||
127 |
n = max_ins_size / (UNIV_PAGE_SIZE / IBUF_PAGE_SIZE_PER_FREE_SPACE); |
|
128 |
||
129 |
if (n == 3) { |
|
130 |
n = 2; |
|
131 |
}
|
|
132 |
||
133 |
if (n > 3) { |
|
134 |
n = 3; |
|
135 |
}
|
|
136 |
||
137 |
return(n); |
|
138 |
}
|
|
139 |
||
140 |
/*************************************************************************
|
|
141 |
Translates the ibuf free bits to the free space on a page in bytes. */
|
|
142 |
UNIV_INLINE
|
|
143 |
ulint
|
|
144 |
ibuf_index_page_calc_free_from_bits( |
|
145 |
/*================================*/
|
|
146 |
/* out: maximum insert size after reorganize for the
|
|
147 |
page */
|
|
148 |
ulint bits) /* in: value for ibuf bitmap bits */ |
|
149 |
{
|
|
150 |
ut_ad(bits < 4); |
|
151 |
||
152 |
if (bits == 3) { |
|
153 |
return(4 * UNIV_PAGE_SIZE / IBUF_PAGE_SIZE_PER_FREE_SPACE); |
|
154 |
}
|
|
155 |
||
156 |
return(bits * UNIV_PAGE_SIZE / IBUF_PAGE_SIZE_PER_FREE_SPACE); |
|
157 |
}
|
|
158 |
||
159 |
/*************************************************************************
|
|
160 |
Translates the free space on a page to a value in the ibuf bitmap.*/
|
|
161 |
UNIV_INLINE
|
|
162 |
ulint
|
|
163 |
ibuf_index_page_calc_free( |
|
164 |
/*======================*/
|
|
165 |
/* out: value for ibuf bitmap bits */
|
|
166 |
page_t* page) /* in: non-unique secondary index page */ |
|
167 |
{
|
|
168 |
return(ibuf_index_page_calc_free_bits( |
|
169 |
page_get_max_insert_size_after_reorganize(page, 1))); |
|
170 |
}
|
|
171 |
||
172 |
/****************************************************************************
|
|
173 |
Updates the free bits of the page in the ibuf bitmap if there is not enough
|
|
174 |
free on the page any more. This is done in a separate mini-transaction, hence
|
|
175 |
this operation does not restrict further work to only ibuf bitmap operations,
|
|
176 |
which would result if the latch to the bitmap page were kept. */
|
|
177 |
UNIV_INLINE
|
|
178 |
void
|
|
179 |
ibuf_update_free_bits_if_full( |
|
180 |
/*==========================*/
|
|
181 |
dict_index_t* index, /* in: index */ |
|
182 |
page_t* page, /* in: index page to which we have added new |
|
183 |
records; the free bits are updated if the
|
|
184 |
index is non-clustered and non-unique and
|
|
185 |
the page level is 0, and the page becomes
|
|
186 |
fuller */
|
|
187 |
ulint max_ins_size,/* in: value of maximum insert size with |
|
188 |
reorganize before the latest operation
|
|
189 |
performed to the page */
|
|
190 |
ulint increase)/* in: upper limit for the additional space |
|
191 |
used in the latest operation, if known, or
|
|
192 |
ULINT_UNDEFINED */
|
|
193 |
{
|
|
194 |
ulint before; |
|
195 |
ulint after; |
|
196 |
||
197 |
before = ibuf_index_page_calc_free_bits(max_ins_size); |
|
198 |
||
199 |
if (max_ins_size >= increase) { |
|
200 |
#if ULINT32_UNDEFINED <= UNIV_PAGE_SIZE
|
|
201 |
# error "ULINT32_UNDEFINED <= UNIV_PAGE_SIZE"
|
|
202 |
#endif
|
|
203 |
after = ibuf_index_page_calc_free_bits(max_ins_size |
|
204 |
- increase); |
|
205 |
#ifdef UNIV_IBUF_DEBUG
|
|
206 |
ut_a(after <= ibuf_index_page_calc_free(page)); |
|
207 |
#endif
|
|
208 |
} else { |
|
209 |
after = ibuf_index_page_calc_free(page); |
|
210 |
}
|
|
211 |
||
212 |
if (after == 0) { |
|
213 |
/* We move the page to the front of the buffer pool LRU list:
|
|
214 |
the purpose of this is to prevent those pages to which we
|
|
215 |
cannot make inserts using the insert buffer from slipping
|
|
216 |
out of the buffer pool */
|
|
217 |
||
218 |
buf_page_make_young(page); |
|
219 |
}
|
|
220 |
||
221 |
if (before > after) { |
|
222 |
ibuf_set_free_bits(index->type, page, after, before); |
|
223 |
}
|
|
224 |
}
|