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