1 /*****************************************************************************
2 
3 Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
4 
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License, version 2.0,
7 as published by the Free Software Foundation.
8 
9 This program is also distributed with certain software (including
10 but not limited to OpenSSL) that is licensed under separate terms,
11 as designated in a particular file or component or in included license
12 documentation.  The authors of MySQL hereby grant you an additional
13 permission to link the program and your derivative works with the
14 separately licensed software that they have included with MySQL.
15 
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 GNU General Public License, version 2.0, for more details.
20 
21 You should have received a copy of the GNU General Public License along with
22 this program; if not, write to the Free Software Foundation, Inc.,
23 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
24 
25 *****************************************************************************/
26 
27 /**************************************************//**
28 @file include/ibuf0ibuf.h
29 Insert buffer
30 
31 Created 7/19/1997 Heikki Tuuri
32 *******************************************************/
33 
34 #ifndef ibuf0ibuf_h
35 #define ibuf0ibuf_h
36 
37 #include "univ.i"
38 
39 #include "mtr0mtr.h"
40 #include "dict0mem.h"
41 #include "fsp0fsp.h"
42 
43 #ifndef UNIV_HOTBACKUP
44 # include "ibuf0types.h"
45 
46 /** Default value for maximum on-disk size of change buffer in terms
47 of percentage of the buffer pool. */
48 #define CHANGE_BUFFER_DEFAULT_SIZE	(25)
49 
50 /* Possible operations buffered in the insert/whatever buffer. See
51 ibuf_insert(). DO NOT CHANGE THE VALUES OF THESE, THEY ARE STORED ON DISK. */
52 typedef enum {
53 	IBUF_OP_INSERT = 0,
54 	IBUF_OP_DELETE_MARK = 1,
55 	IBUF_OP_DELETE = 2,
56 
57 	/* Number of different operation types. */
58 	IBUF_OP_COUNT = 3
59 } ibuf_op_t;
60 
61 /** Combinations of operations that can be buffered.  Because the enum
62 values are used for indexing innobase_change_buffering_values[], they
63 should start at 0 and there should not be any gaps. */
64 typedef enum {
65 	IBUF_USE_NONE = 0,
66 	IBUF_USE_INSERT,	/* insert */
67 	IBUF_USE_DELETE_MARK,	/* delete */
68 	IBUF_USE_INSERT_DELETE_MARK,	/* insert+delete */
69 	IBUF_USE_DELETE,	/* delete+purge */
70 	IBUF_USE_ALL,		/* insert+delete+purge */
71 
72 	IBUF_USE_COUNT		/* number of entries in ibuf_use_t */
73 } ibuf_use_t;
74 
75 /** Operations that can currently be buffered. */
76 extern ibuf_use_t	ibuf_use;
77 
78 /** The insert buffer control structure */
79 extern ibuf_t*		ibuf;
80 
81 /* The purpose of the insert buffer is to reduce random disk access.
82 When we wish to insert a record into a non-unique secondary index and
83 the B-tree leaf page where the record belongs to is not in the buffer
84 pool, we insert the record into the insert buffer B-tree, indexed by
85 (space_id, page_no).  When the page is eventually read into the buffer
86 pool, we look up the insert buffer B-tree for any modifications to the
87 page, and apply these upon the completion of the read operation.  This
88 is called the insert buffer merge. */
89 
90 /* The insert buffer merge must always succeed.  To guarantee this,
91 the insert buffer subsystem keeps track of the free space in pages for
92 which it can buffer operations.  Two bits per page in the insert
93 buffer bitmap indicate the available space in coarse increments.  The
94 free bits in the insert buffer bitmap must never exceed the free space
95 on a page.  It is safe to decrement or reset the bits in the bitmap in
96 a mini-transaction that is committed before the mini-transaction that
97 affects the free space.  It is unsafe to increment the bits in a
98 separately committed mini-transaction, because in crash recovery, the
99 free bits could momentarily be set too high. */
100 
101 /******************************************************************//**
102 Creates the insert buffer data structure at a database startup. */
103 UNIV_INTERN
104 void
105 ibuf_init_at_db_start(void);
106 /*=======================*/
107 /*********************************************************************//**
108 Updates the max_size value for ibuf. */
109 UNIV_INTERN
110 void
111 ibuf_max_size_update(
112 /*=================*/
113 	ulint	new_val);	/*!< in: new value in terms of
114 				percentage of the buffer pool size */
115 /*********************************************************************//**
116 Reads the biggest tablespace id from the high end of the insert buffer
117 tree and updates the counter in fil_system. */
118 UNIV_INTERN
119 void
120 ibuf_update_max_tablespace_id(void);
121 /*===============================*/
122 /***************************************************************//**
123 Starts an insert buffer mini-transaction. */
124 UNIV_INLINE
125 void
126 ibuf_mtr_start(
127 /*===========*/
128 	mtr_t*	mtr)	/*!< out: mini-transaction */
129 	MY_ATTRIBUTE((nonnull));
130 /***************************************************************//**
131 Commits an insert buffer mini-transaction. */
132 UNIV_INLINE
133 void
134 ibuf_mtr_commit(
135 /*============*/
136 	mtr_t*	mtr)	/*!< in/out: mini-transaction */
137 	MY_ATTRIBUTE((nonnull));
138 /*********************************************************************//**
139 Initializes an ibuf bitmap page. */
140 UNIV_INTERN
141 void
142 ibuf_bitmap_page_init(
143 /*==================*/
144 	buf_block_t*	block,	/*!< in: bitmap page */
145 	mtr_t*		mtr);	/*!< in: mtr */
146 /************************************************************************//**
147 Resets the free bits of the page in the ibuf bitmap. This is done in a
148 separate mini-transaction, hence this operation does not restrict
149 further work to only ibuf bitmap operations, which would result if the
150 latch to the bitmap page were kept.  NOTE: The free bits in the insert
151 buffer bitmap must never exceed the free space on a page.  It is safe
152 to decrement or reset the bits in the bitmap in a mini-transaction
153 that is committed before the mini-transaction that affects the free
154 space. */
155 UNIV_INTERN
156 void
157 ibuf_reset_free_bits(
158 /*=================*/
159 	buf_block_t*	block);	/*!< in: index page; free bits are set to 0
160 				if the index is a non-clustered
161 				non-unique, and page level is 0 */
162 /************************************************************************//**
163 Updates the free bits of an uncompressed page in the ibuf bitmap if
164 there is not enough free on the page any more.  This is done in a
165 separate mini-transaction, hence this operation does not restrict
166 further work to only ibuf bitmap operations, which would result if the
167 latch to the bitmap page were kept.  NOTE: The free bits in the insert
168 buffer bitmap must never exceed the free space on a page.  It is
169 unsafe to increment the bits in a separately committed
170 mini-transaction, because in crash recovery, the free bits could
171 momentarily be set too high.  It is only safe to use this function for
172 decrementing the free bits.  Should more free space become available,
173 we must not update the free bits here, because that would break crash
174 recovery. */
175 UNIV_INLINE
176 void
177 ibuf_update_free_bits_if_full(
178 /*==========================*/
179 	buf_block_t*	block,	/*!< in: index page to which we have added new
180 				records; the free bits are updated if the
181 				index is non-clustered and non-unique and
182 				the page level is 0, and the page becomes
183 				fuller */
184 	ulint		max_ins_size,/*!< in: value of maximum insert size with
185 				reorganize before the latest operation
186 				performed to the page */
187 	ulint		increase);/*!< in: upper limit for the additional space
188 				used in the latest operation, if known, or
189 				ULINT_UNDEFINED */
190 /**********************************************************************//**
191 Updates the free bits for an uncompressed page to reflect the present
192 state.  Does this in the mtr given, which means that the latching
193 order rules virtually prevent any further operations for this OS
194 thread until mtr is committed.  NOTE: The free bits in the insert
195 buffer bitmap must never exceed the free space on a page.  It is safe
196 to set the free bits in the same mini-transaction that updated the
197 page. */
198 UNIV_INTERN
199 void
200 ibuf_update_free_bits_low(
201 /*======================*/
202 	const buf_block_t*	block,		/*!< in: index page */
203 	ulint			max_ins_size,	/*!< in: value of
204 						maximum insert size
205 						with reorganize before
206 						the latest operation
207 						performed to the page */
208 	mtr_t*			mtr);		/*!< in/out: mtr */
209 /**********************************************************************//**
210 Updates the free bits for a compressed page to reflect the present
211 state.  Does this in the mtr given, which means that the latching
212 order rules virtually prevent any further operations for this OS
213 thread until mtr is committed.  NOTE: The free bits in the insert
214 buffer bitmap must never exceed the free space on a page.  It is safe
215 to set the free bits in the same mini-transaction that updated the
216 page. */
217 UNIV_INTERN
218 void
219 ibuf_update_free_bits_zip(
220 /*======================*/
221 	buf_block_t*	block,	/*!< in/out: index page */
222 	mtr_t*		mtr);	/*!< in/out: mtr */
223 /**********************************************************************//**
224 Updates the free bits for the two pages to reflect the present state.
225 Does this in the mtr given, which means that the latching order rules
226 virtually prevent any further operations until mtr is committed.
227 NOTE: The free bits in the insert buffer bitmap must never exceed the
228 free space on a page.  It is safe to set the free bits in the same
229 mini-transaction that updated the pages. */
230 UNIV_INTERN
231 void
232 ibuf_update_free_bits_for_two_pages_low(
233 /*====================================*/
234 	ulint		zip_size,/*!< in: compressed page size in bytes;
235 				0 for uncompressed pages */
236 	buf_block_t*	block1,	/*!< in: index page */
237 	buf_block_t*	block2,	/*!< in: index page */
238 	mtr_t*		mtr);	/*!< in: mtr */
239 /**********************************************************************//**
240 A basic partial test if an insert to the insert buffer could be possible and
241 recommended. */
242 UNIV_INLINE
243 ibool
244 ibuf_should_try(
245 /*============*/
246 	dict_index_t*	index,			/*!< in: index where to insert */
247 	ulint		ignore_sec_unique);	/*!< in: if != 0, we should
248 						ignore UNIQUE constraint on
249 						a secondary index when we
250 						decide */
251 /******************************************************************//**
252 Returns TRUE if the current OS thread is performing an insert buffer
253 routine.
254 
255 For instance, a read-ahead of non-ibuf pages is forbidden by threads
256 that are executing an insert buffer routine.
257 @return TRUE if inside an insert buffer routine */
258 UNIV_INLINE
259 ibool
260 ibuf_inside(
261 /*========*/
262 	const mtr_t*	mtr)	/*!< in: mini-transaction */
263 	MY_ATTRIBUTE((nonnull, pure));
264 /***********************************************************************//**
265 Checks if a page address is an ibuf bitmap page (level 3 page) address.
266 @return	TRUE if a bitmap page */
267 UNIV_INLINE
268 ibool
269 ibuf_bitmap_page(
270 /*=============*/
271 	ulint	zip_size,/*!< in: compressed page size in bytes;
272 			0 for uncompressed pages */
273 	ulint	page_no);/*!< in: page number */
274 /***********************************************************************//**
275 Checks if a page is a level 2 or 3 page in the ibuf hierarchy of pages.
276 Must not be called when recv_no_ibuf_operations==TRUE.
277 @return	TRUE if level 2 or level 3 page */
278 UNIV_INTERN
279 ibool
280 ibuf_page_low(
281 /*==========*/
282 	ulint		space,	/*!< in: space id */
283 	ulint		zip_size,/*!< in: compressed page size in bytes, or 0 */
284 	ulint		page_no,/*!< in: page number */
285 #ifdef UNIV_DEBUG
286 	ibool		x_latch,/*!< in: FALSE if relaxed check
287 				(avoid latching the bitmap page) */
288 #endif /* UNIV_DEBUG */
289 	const char*	file,	/*!< in: file name */
290 	ulint		line,	/*!< in: line where called */
291 	mtr_t*		mtr)	/*!< in: mtr which will contain an
292 				x-latch to the bitmap page if the page
293 				is not one of the fixed address ibuf
294 				pages, or NULL, in which case a new
295 				transaction is created. */
296 	MY_ATTRIBUTE((warn_unused_result));
297 #ifdef UNIV_DEBUG
298 /** Checks if a page is a level 2 or 3 page in the ibuf hierarchy of
299 pages.  Must not be called when recv_no_ibuf_operations==TRUE.
300 @param space	tablespace identifier
301 @param zip_size	compressed page size in bytes, or 0
302 @param page_no	page number
303 @param mtr	mini-transaction or NULL
304 @return TRUE if level 2 or level 3 page */
305 # define ibuf_page(space, zip_size, page_no, mtr)			\
306 	ibuf_page_low(space, zip_size, page_no, TRUE, __FILE__, __LINE__, mtr)
307 #else /* UVIV_DEBUG */
308 /** Checks if a page is a level 2 or 3 page in the ibuf hierarchy of
309 pages.  Must not be called when recv_no_ibuf_operations==TRUE.
310 @param space	tablespace identifier
311 @param zip_size	compressed page size in bytes, or 0
312 @param page_no	page number
313 @param mtr	mini-transaction or NULL
314 @return TRUE if level 2 or level 3 page */
315 # define ibuf_page(space, zip_size, page_no, mtr)			\
316 	ibuf_page_low(space, zip_size, page_no, __FILE__, __LINE__, mtr)
317 #endif /* UVIV_DEBUG */
318 /***********************************************************************//**
319 Frees excess pages from the ibuf free list. This function is called when an OS
320 thread calls fsp services to allocate a new file segment, or a new page to a
321 file segment, and the thread did not own the fsp latch before this call. */
322 UNIV_INTERN
323 void
324 ibuf_free_excess_pages(void);
325 /*========================*/
326 /*********************************************************************//**
327 Buffer an operation in the insert/delete buffer, instead of doing it
328 directly to the disk page, if this is possible. Does not do it if the index
329 is clustered or unique.
330 @return	TRUE if success */
331 UNIV_INTERN
332 ibool
333 ibuf_insert(
334 /*========*/
335 	ibuf_op_t	op,	/*!< in: operation type */
336 	const dtuple_t*	entry,	/*!< in: index entry to insert */
337 	dict_index_t*	index,	/*!< in: index where to insert */
338 	ulint		space,	/*!< in: space id where to insert */
339 	ulint		zip_size,/*!< in: compressed page size in bytes, or 0 */
340 	ulint		page_no,/*!< in: page number where to insert */
341 	que_thr_t*	thr);	/*!< in: query thread */
342 /*********************************************************************//**
343 When an index page is read from a disk to the buffer pool, this function
344 applies any buffered operations to the page and deletes the entries from the
345 insert buffer. If the page is not read, but created in the buffer pool, this
346 function deletes its buffered entries from the insert buffer; there can
347 exist entries for such a page if the page belonged to an index which
348 subsequently was dropped. */
349 UNIV_INTERN
350 void
351 ibuf_merge_or_delete_for_page(
352 /*==========================*/
353 	buf_block_t*	block,	/*!< in: if page has been read from
354 				disk, pointer to the page x-latched,
355 				else NULL */
356 	ulint		space,	/*!< in: space id of the index page */
357 	ulint		page_no,/*!< in: page number of the index page */
358 	ulint		zip_size,/*!< in: compressed page size in bytes,
359 				or 0 */
360 	ibool		update_ibuf_bitmap);/*!< in: normally this is set
361 				to TRUE, but if we have deleted or are
362 				deleting the tablespace, then we
363 				naturally do not want to update a
364 				non-existent bitmap page */
365 /*********************************************************************//**
366 Deletes all entries in the insert buffer for a given space id. This is used
367 in DISCARD TABLESPACE and IMPORT TABLESPACE.
368 NOTE: this does not update the page free bitmaps in the space. The space will
369 become CORRUPT when you call this function! */
370 UNIV_INTERN
371 void
372 ibuf_delete_for_discarded_space(
373 /*============================*/
374 	ulint	space);	/*!< in: space id */
375 /** Contract the change buffer by reading pages to the buffer pool.
376 @param[in]	full		If true, do a full contraction based
377 on PCT_IO(100). If false, the size of contract batch is determined
378 based on the current size of the change buffer.
379 @return a lower limit for the combined size in bytes of entries which
380 will be merged from ibuf trees to the pages read, 0 if ibuf is
381 empty */
382 UNIV_INTERN
383 ulint
384 ibuf_merge_in_background(
385 	bool	full);	/*!< in: TRUE if the caller wants to
386 			do a full contract based on PCT_IO(100).
387 			If FALSE then the size of contract
388 			batch is determined based on the
389 			current size of the ibuf tree. */
390 
391 /** Contracts insert buffer trees by reading pages referring to space_id
392 to the buffer pool.
393 @returns number of pages merged.*/
394 UNIV_INTERN
395 ulint
396 ibuf_merge_space(
397 /*=============*/
398 	ulint	space);	/*!< in: space id */
399 
400 #endif /* !UNIV_HOTBACKUP */
401 /*********************************************************************//**
402 Parses a redo log record of an ibuf bitmap page init.
403 @return	end of log record or NULL */
404 UNIV_INTERN
405 byte*
406 ibuf_parse_bitmap_init(
407 /*===================*/
408 	byte*		ptr,	/*!< in: buffer */
409 	byte*		end_ptr,/*!< in: buffer end */
410 	buf_block_t*	block,	/*!< in: block or NULL */
411 	mtr_t*		mtr);	/*!< in: mtr or NULL */
412 #ifndef UNIV_HOTBACKUP
413 #ifdef UNIV_IBUF_COUNT_DEBUG
414 /******************************************************************//**
415 Gets the ibuf count for a given page.
416 @return number of entries in the insert buffer currently buffered for
417 this page */
418 UNIV_INTERN
419 ulint
420 ibuf_count_get(
421 /*===========*/
422 	ulint	space,	/*!< in: space id */
423 	ulint	page_no);/*!< in: page number */
424 #endif
425 /******************************************************************//**
426 Looks if the insert buffer is empty.
427 @return	true if empty */
428 UNIV_INTERN
429 bool
430 ibuf_is_empty(void);
431 /*===============*/
432 /******************************************************************//**
433 Prints info of ibuf. */
434 UNIV_INTERN
435 void
436 ibuf_print(
437 /*=======*/
438 	FILE*	file);	/*!< in: file where to print */
439 /********************************************************************
440 Read the first two bytes from a record's fourth field (counter field in new
441 records; something else in older records).
442 @return	"counter" field, or ULINT_UNDEFINED if for some reason it can't be read */
443 UNIV_INTERN
444 ulint
445 ibuf_rec_get_counter(
446 /*=================*/
447 	const rec_t*	rec);	/*!< in: ibuf record */
448 /******************************************************************//**
449 Closes insert buffer and frees the data structures. */
450 UNIV_INTERN
451 void
452 ibuf_close(void);
453 /*============*/
454 
455 /******************************************************************//**
456 Checks the insert buffer bitmaps on IMPORT TABLESPACE.
457 @return DB_SUCCESS or error code */
458 UNIV_INTERN
459 dberr_t
460 ibuf_check_bitmap_on_import(
461 /*========================*/
462 	const trx_t*	trx,		/*!< in: transaction */
463 	ulint		space_id)	/*!< in: tablespace identifier */
464 	MY_ATTRIBUTE((nonnull, warn_unused_result));
465 
466 #define IBUF_HEADER_PAGE_NO	FSP_IBUF_HEADER_PAGE_NO
467 #define IBUF_TREE_ROOT_PAGE_NO	FSP_IBUF_TREE_ROOT_PAGE_NO
468 
469 #endif /* !UNIV_HOTBACKUP */
470 
471 /* The ibuf header page currently contains only the file segment header
472 for the file segment from which the pages for the ibuf tree are allocated */
473 #define IBUF_HEADER		PAGE_DATA
474 #define	IBUF_TREE_SEG_HEADER	0	/* fseg header for ibuf tree */
475 
476 /* The insert buffer tree itself is always located in space 0. */
477 #define IBUF_SPACE_ID		0
478 
479 #ifndef UNIV_NONINL
480 #include "ibuf0ibuf.ic"
481 #endif
482 
483 #endif
484