MySQL 26.7.0
Source Code Documentation
btr0btr.h
Go to the documentation of this file.
1/*****************************************************************************
2
3Copyright (c) 1994, 2026, Oracle and/or its affiliates.
4Copyright (c) 2012, Facebook Inc.
5
6This program is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License, version 2.0, as published by the
8Free Software Foundation.
9
10This program is designed to work with certain software (including
11but not limited to OpenSSL) that is licensed under separate terms,
12as designated in a particular file or component or in included license
13documentation. The authors of MySQL hereby grant you an additional
14permission to link the program and your derivative works with the
15separately licensed software that they have either included with
16the program or referenced in the documentation.
17
18This program is distributed in the hope that it will be useful, but WITHOUT
19ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
20FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
21for more details.
22
23You should have received a copy of the GNU General Public License along with
24this program; if not, write to the Free Software Foundation, Inc.,
2551 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26
27*****************************************************************************/
28
29/** @file include/btr0btr.h
30 The B-tree
31
32 Created 6/2/1994 Heikki Tuuri
33 *******************************************************/
34
35#ifndef btr0btr_h
36#define btr0btr_h
37
38#include "btr0types.h"
39#include "data0data.h"
40#include "dict0dict.h"
41#include "gis0type.h"
42#include "mtr0mtr.h"
43#include "page0cur.h"
44#include "univ.i"
45
46/** Maximum record size which can be stored on a page, without using the
47special big record storage structure */
48#define BTR_PAGE_MAX_REC_SIZE (UNIV_PAGE_SIZE / 2 - 200)
49
50/** @brief Maximum depth of a B-tree in InnoDB.
51
52Note that this isn't a maximum as such; none of the tree operations
53avoid producing trees bigger than this. It is instead a "max depth
54that other code must work with", useful for e.g. fixed-size arrays
55that must store some information about each level in a tree. In other
56words: if a B-tree with bigger depth than this is encountered, it is
57not acceptable for it to lead to mysterious memory corruption, but it
58is acceptable for the program to die with a clear assert failure. */
59constexpr uint32_t BTR_MAX_LEVELS = 100;
60
61/** PAGE_INDEX_ID value for freed index B-trees. */
63
64/** Latching modes for btr_cur_search_to_nth_level(). */
65enum btr_latch_mode : size_t {
66 /** Search a record on a leaf page and S-latch it. */
68 /** (Prepare to) modify a record on a leaf page and X-latch it. */
70 /** Obtain no latches. */
72 /** Start modifying the entire B-tree. */
74 /** Continue modifying the entire B-tree. */
76 /** Search the previous record. */
78 /** Modify the previous record. */
80 /** Start searching the entire B-tree. */
82 /** Continue searching the entire B-tree. */
84};
85
86/* BTR_INSERT, BTR_DELETE and BTR_DELETE_MARK are mutually exclusive. */
87
88/** If this is ORed to btr_latch_mode, it means that the search tuple
89will be inserted to the index, at the searched position.
90When the record is not in the buffer pool, try to use the insert buffer. */
91constexpr size_t BTR_INSERT = 512;
92
93/** This flag ORed to btr_latch_mode says that we do the search in query
94optimization */
95constexpr size_t BTR_ESTIMATE = 1024;
96
97/** This flag ORed to BTR_INSERT says that we can ignore possible
98UNIQUE definition on secondary indexes when we decide if we can use
99the insert buffer to speed up inserts */
100constexpr size_t BTR_IGNORE_SEC_UNIQUE = 2048;
101
102/** Try to delete mark the record at the searched position using the
103insert/delete buffer when the record is not in the buffer pool. */
104constexpr size_t BTR_DELETE_MARK = 4096;
105
106/** Try to purge the record at the searched position using the insert/delete
107buffer when the record is not in the buffer pool. */
108constexpr size_t BTR_DELETE = 8192;
109
110/** In the case of BTR_SEARCH_LEAF or BTR_MODIFY_LEAF, the caller is
111already holding an S latch on the index tree */
112constexpr size_t BTR_ALREADY_S_LATCHED = 16384;
113
114/** In the case of BTR_MODIFY_TREE, the caller specifies the intention
115to insert record only. It is used to optimize block->lock range.*/
116constexpr size_t BTR_LATCH_FOR_INSERT = 32768;
117
118/** In the case of BTR_MODIFY_TREE, the caller specifies the intention
119to delete record only. It is used to optimize block->lock range.*/
120constexpr size_t BTR_LATCH_FOR_DELETE = 65536;
121
122/** This flag is for undo insert of rtree. For rtree, we need this flag
123to find proper rec to undo insert.*/
124constexpr size_t BTR_RTREE_UNDO_INS = 131072;
125
126/** In the case of BTR_MODIFY_LEAF, the caller intends to allocate or
127free the pages of externally stored fields. */
128constexpr size_t BTR_MODIFY_EXTERNAL = 262144;
129
130/** Try to delete mark the record at the searched position when the
131record is in spatial index */
132constexpr size_t BTR_RTREE_DELETE_MARK = 524288;
133
134using Page_range_t = std::pair<page_no_t, page_no_t>;
135
137 return latch_mode &
142}
143
145 return latch_mode &
147}
148
149/** Report that an index page is corrupted. */
150void btr_corruption_report(const buf_block_t *block, /*!< in: corrupted block */
151 const dict_index_t *index) /*!< in: index tree */
152 UNIV_COLD;
153
154/** Assert that a B-tree page is not corrupted.
155@param block buffer block containing a B-tree page
156@param index the B-tree index */
157inline void btr_assert_not_corrupted(const buf_block_t *block,
158 const dict_index_t *index) {
159 if (page_is_comp(buf_block_get_frame(block)) !=
162 ut_error;
163 }
164}
165
166/** Gets the root node of a tree and sx-latches it for segment access.
167 @return root page, sx-latched */
168page_t *btr_root_get(const dict_index_t *index, /*!< in: index tree */
169 mtr_t *mtr); /*!< in: mtr */
170
171/** Checks and adjusts the root node of a tree during IMPORT TABLESPACE.
172 @return error code, or DB_SUCCESS */
174 const dict_index_t *index); /*!< in: index tree */
175
176/** Gets the height of the B-tree (the level of the root, when the leaf
177 level is assumed to be 0). The caller must hold an S or X latch on
178 the index.
179 @return tree height (level of the root) */
180[[nodiscard]] ulint btr_height_get(dict_index_t *index, /*!< in: index tree */
181 mtr_t *mtr); /*!< in/out: mini-transaction */
182
183#ifndef UNIV_HOTBACKUP
184/** Gets a buffer page and declares its latching order level.
185@param[in] page_id Page id
186@param[in] page_size Page size
187@param[in] mode Latch mode
188@param[in] location Location from where this method is called.
189@param[in] index Index tree, may be NULL if it is not an insert
190 buffer tree
191@param[in,out] mtr Mini-transaction
192@return block */
194 const page_id_t &page_id, const page_size_t &page_size, ulint mode,
195 ut::Location location, IF_DEBUG(const dict_index_t *index, ) mtr_t *mtr);
196
197/** Gets a buffer page and declares its latching order level.
198@param page_id Tablespace/page identifier
199@param page_size Page size
200@param mode Latch mode
201@param[in] location Location from where this method is called.
202@param index Index tree, may be NULL if not the insert buffer tree
203@param mtr Mini-transaction handle
204@return the block descriptor */
205static inline buf_block_t *btr_block_get(const page_id_t &page_id,
206 const page_size_t &page_size,
207 ulint mode, ut::Location location,
208 const dict_index_t *index,
209 mtr_t *mtr) {
210 return btr_block_get_func(page_id, page_size, mode, location,
211 IF_DEBUG(index, ) mtr);
212}
213
214#endif /* !UNIV_HOTBACKUP */
215
216/** Gets the index id field of a page.
217 @return index id */
218[[nodiscard]] static inline space_index_t btr_page_get_index_id(
219 const page_t *page); /*!< in: index page */
220/** Gets the node level field in an index page.
221 @param[in] page index page
222 @return level, leaf level == 0 */
223[[nodiscard]] static inline ulint btr_page_get_level(const page_t *page);
224/** Gets the next index page number.
225@param[in] page Index page.
226@param[in] mtr Mini-transaction handle.
227@return next page number */
228[[nodiscard]] static inline page_no_t btr_page_get_next(const page_t *page,
229 mtr_t *mtr);
230/** Gets the previous index page number.
231@param[in] page Index page.
232@param[in] mtr Mini-transaction handle.
233@return prev page number */
234[[nodiscard]] static inline page_no_t btr_page_get_prev(const page_t *page,
235 mtr_t *mtr);
236
237#ifndef UNIV_HOTBACKUP
238/** Releases the latch on a leaf page and bufferunfixes it.
239@param[in] block buffer block
240@param[in] latch_mode BTR_SEARCH_LEAF or BTR_MODIFY_LEAF
241@param[in] mtr mtr */
242static inline void btr_leaf_page_release(buf_block_t *block, ulint latch_mode,
243 mtr_t *mtr);
244#endif /* !UNIV_HOTBACKUP */
245
246/** Gets the child node file address in a node pointer.
247 NOTE: the offsets array must contain all offsets for the record since
248 we read the last field according to offsets and assume that it contains
249 the child page number. In other words offsets must have been retrieved
250 with rec_get_offsets(n_fields=ULINT_UNDEFINED).
251 @param[in] rec node Pointer record
252 @param[in] offsets Array returned by rec_get_offsets()
253 @return child node address */
254[[nodiscard]] static inline page_no_t btr_node_ptr_get_child_page_no(
255 const rec_t *rec, const ulint *offsets);
256
257/** Returns the child page of a node pointer and sx-latches it.
258@param[in] node_ptr node pointer
259@param[in] index index
260@param[in] offsets array returned by rec_get_offsets()
261@param[in] mtr mtr
262@param[in] type latch type
263@return child page, latched as per the type */
265 const ulint *offsets, mtr_t *mtr,
267
268/** Create the root node for a new index tree.
269@param[in] type Type of the index
270@param[in] space Space where created
271@param[in] index_id Index id
272@param[in] index Index tree
273@param[in,out] mtr Mini-transaction
274@return page number of the created root
275@retval FIL_NULL if did not succeed */
277 dict_index_t *index, mtr_t *mtr);
278
279/** Free a persistent index tree if it exists.
280@param[in] page_id Root page id
281@param[in] page_size Page size
282@param[in] index_id PAGE_INDEX_ID contents
283@param[in,out] mtr Mini-transaction */
284void btr_free_if_exists(const page_id_t &page_id, const page_size_t &page_size,
285 space_index_t index_id, mtr_t *mtr);
286
287/** Free an index tree in a temporary tablespace.
288@param[in] page_id root page id
289@param[in] page_size page size */
290void btr_free(const page_id_t &page_id, const page_size_t &page_size);
291
292/** Truncate an index tree. We just free all except the root.
293Currently, this function is only specific for clustered indexes and the only
294caller is DDTableBuffer which manages a table with only a clustered index.
295It is up to the caller to ensure atomicity and to ensure correct recovery by
296calling btr_truncate_recover().
297@param[in] index clustered index */
298void btr_truncate(const dict_index_t *index);
299
300/** Recovery function for btr_truncate. We will check if there is a
301crash during btr_truncate, if so, do recover it, if not, do nothing.
302@param[in] index clustered index */
304
305/** Makes tree one level higher by splitting the root, and inserts
306 the tuple. It is assumed that mtr contains an x-latch on the tree.
307 NOTE that the operation of this function must always succeed,
308 we cannot reverse it: therefore enough free disk space must be
309 guaranteed to be available before this function is called.
310 @return inserted record */
311[[nodiscard]] rec_t *btr_root_raise_and_insert(
312 uint32_t flags, /*!< in: undo logging and locking flags */
313 btr_cur_t *cursor, /*!< in: cursor at which to insert: must be
314 on the root page; when the function returns,
315 the cursor is positioned on the predecessor
316 of the inserted record */
317 ulint **offsets, /*!< out: offsets on inserted record */
318 mem_heap_t **heap, /*!< in/out: pointer to memory heap
319 that can be emptied, or NULL */
320 const dtuple_t *tuple, /*!< in: tuple to insert */
321 mtr_t *mtr); /*!< in: mtr */
322/** Reorganizes an index page.
323
324IMPORTANT: On success, the caller will have to update IBUF_BITMAP_FREE
325if this is a compressed leaf page in a secondary index. This has to
326be done either within the same mini-transaction, or by invoking
327ibuf_reset_free_bits() before mtr_commit(). On uncompressed pages,
328IBUF_BITMAP_FREE is unaffected by reorganization.
329
330@param[in] recovery True if called in recovery: locks should not be updated,
331i.e., there cannot exist locks on the page, and a hash index should not be
332dropped: it cannot exist.
333@param[in] z_level Compression level to be used if dealing with compressed
334page.
335@param[in,out] cursor Page cursor.
336@param[in] index The index tree of the page.
337@param[in,out] mtr Mini-transaction
338@retval true if the operation was successful
339@retval false if it is a compressed page, and re-compression failed */
340[[nodiscard]] bool btr_page_reorganize_low(bool recovery, ulint z_level,
341 page_cur_t *cursor,
342 dict_index_t *index, mtr_t *mtr);
343
344/** Reorganizes an index page.
345
346IMPORTANT: On success, the caller will have to update IBUF_BITMAP_FREE
347if this is a compressed leaf page in a secondary index. This has to
348be done either within the same mini-transaction, or by invoking
349ibuf_reset_free_bits() before mtr_commit(). On uncompressed pages,
350IBUF_BITMAP_FREE is unaffected by reorganization.
351
352@param[in,out] cursor Page cursor
353@param[in] index The index tree of the page
354@param[in,out] mtr Mini-transaction
355@retval true if the operation was successful
356@retval false if it is a compressed page, and recompression failed */
358
359/** Decides if the page should be split at the convergence point of
360 inserts converging to left.
361 @return true if split recommended */
362[[nodiscard]] bool btr_page_get_split_rec_to_left(
363 btr_cur_t *cursor, /*!< in: cursor at which to insert */
364 rec_t **split_rec); /*!< out: if split recommended,
365 the first record on upper half page,
366 or NULL if tuple should be first */
367/** Decides if the page should be split at the convergence point of
368 inserts converging to right.
369 @return true if split recommended */
370[[nodiscard]] bool btr_page_get_split_rec_to_right(
371 btr_cur_t *cursor, /*!< in: cursor at which to insert */
372 rec_t **split_rec); /*!< out: if split recommended,
373 the first record on upper half page,
374 or NULL if tuple should be first */
375
376/** Splits an index page to halves and inserts the tuple. It is assumed
377 that mtr holds an x-latch to the index tree. NOTE: the tree x-latch is
378 released within this function! NOTE that the operation of this
379 function must always succeed, we cannot reverse it: therefore enough
380 free disk space (2 pages) must be guaranteed to be available before
381 this function is called.
382
383 @return inserted record */
384[[nodiscard]] rec_t *btr_page_split_and_insert(
385 uint32_t flags, /*!< in: undo logging and locking flags */
386 btr_cur_t *cursor, /*!< in: cursor at which to insert; when the
387 function returns, the cursor is positioned
388 on the predecessor of the inserted record */
389 ulint **offsets, /*!< out: offsets on inserted record */
390 mem_heap_t **heap, /*!< in/out: pointer to memory heap
391 that can be emptied, or NULL */
392 const dtuple_t *tuple, /*!< in: tuple to insert */
393 mtr_t *mtr); /*!< in: mtr */
394/** Inserts a data tuple to a tree on a non-leaf level. It is assumed
395 that mtr holds an x-latch on the tree.
396 @param[in] flags undo logging and locking flags
397 @param[in] index index
398 @param[in] level level, must be > 0
399 @param[in] tuple the record to be inserted
400 @param[in] location location where called
401 @param[in] mtr mtr */
403 ulint level, dtuple_t *tuple,
404 ut::Location location, mtr_t *mtr);
405
406/** Sets a record as the predefined minimum record.
407@param[in,out] rec Record
408@param[in] mtr Mini-transaction
409*/
410void btr_set_min_rec_mark(rec_t *rec, mtr_t *mtr);
411
412/** Removes a record as the predefined minimum record.
413@param[in] block buffer block containing the record.
414@param[in] rec the record who info bits will be modified by clearing
415 the REC_INFO_MIN_REC_FLAG bit.
416@param[in] mtr mini transaction context. */
417void btr_unset_min_rec_mark(buf_block_t *block, rec_t *rec, mtr_t *mtr);
418
419/** Deletes on the upper level the node pointer to a page.
420@param[in] index Index tree
421@param[in] block Page whose node pointer is deleted
422@param[in] mtr Mini-transaction
423*/
425#ifdef UNIV_DEBUG
426/** Asserts that the node pointer to a page is appropriate.
427 @param[in] index index tree
428 @param[in] block index page
429 @param[in] mtr mtr
430 @return true */
432#endif /* UNIV_DEBUG */
433/** Tries to merge the page first to the left immediate brother if such a
434 brother exists, and the node pointers to the current page and to the brother
435 reside on the same page. If the left brother does not satisfy these
436 conditions, looks at the right brother. If the page is the only one on that
437 level lifts the records of the page to the father page, thus reducing the
438 tree height. It is assumed that mtr holds an x-latch on the tree and on the
439 page. If cursor is on the leaf level, mtr must also hold x-latches to the
440 brothers, if they exist.
441 @param[in,out] cursor cursor on the page to merge or lift; the page must not be
442 empty: when deleting records, use btr_discard_page() if the page would become
443 empty
444 @param[in] adjust true if should adjust the cursor position even if compression
445 occurs.
446 @param[in,out] mtr mini-transaction
447 @return true on success */
448bool btr_compress(btr_cur_t *cursor, bool adjust, mtr_t *mtr);
449/** Discards a page from a B-tree. This is used to remove the last record from
450 a B-tree page: the whole page must be removed at the same time. This cannot
451 be used for the root page, which is allowed to be empty. */
452void btr_discard_page(btr_cur_t *cursor, /*!< in: cursor on the page to
453 discard: not on the root page */
454 mtr_t *mtr); /*!< in: mtr */
455/** Parses the redo log record for setting an index record as the predefined
456 minimum record.
457 @return end of log record or NULL */
458[[nodiscard]] const byte *btr_parse_set_min_rec_mark(
459 const byte *ptr, /*!< in: buffer */
460 const byte *end_ptr, /*!< in: buffer end */
461 ulint comp, /*!< in: nonzero=compact page format */
462 page_t *page, /*!< in: page or NULL */
463 mtr_t *mtr); /*!< in: mtr or NULL */
464/** Parses a redo log record of reorganizing a page.
465 @return end of log record or NULL */
466[[nodiscard]] const byte *btr_parse_page_reorganize(
467 const byte *ptr, /*!< in: buffer */
468 const byte *end_ptr, /*!< in: buffer end */
469 dict_index_t *index, /*!< in: record descriptor */
470 bool compressed, /*!< in: true if compressed page */
471 buf_block_t *block, /*!< in: page to be reorganized, or NULL */
472 mtr_t *mtr); /*!< in: mtr or NULL */
473/** Gets the number of pages in a B-tree.
474 @return number of pages, or ULINT_UNDEFINED if the index is unavailable */
475[[nodiscard]] ulint btr_get_size(
476 dict_index_t *index, /*!< in: index */
477 ulint flag, /*!< in: BTR_N_LEAF_PAGES or BTR_TOTAL_SIZE */
478 mtr_t *mtr); /*!< in/out: mini-transaction where index
479 is s-latched */
480
481#ifdef UNIV_DEBUG
482#define btr_page_alloc(index, hint_page_no, file_direction, level, mtr, \
483 init_mtr) \
484 btr_page_alloc_priv(index, hint_page_no, file_direction, level, mtr, \
485 init_mtr, UT_LOCATION_HERE)
486#else /* UNIV_DEBUG */
487#define btr_page_alloc(index, hint_page_no, file_direction, level, mtr, \
488 init_mtr) \
489 btr_page_alloc_priv(index, hint_page_no, file_direction, level, mtr, init_mtr)
490#endif /* UNIV_DEBUG */
491
492/** Allocates a new file page to be used in an index tree. NOTE: we assume
493that the caller has made the reservation for free extents!
494@param[in] index Index tree
495@param[in] hint_page_no Hint of a good page
496@param[in] file_direction Direction where a possible page split is made
497@param[in] level Level where the page is placed in the tree
498@param[in,out] mtr Mini-transaction for the allocation
499@param[in,out] init_mtr Mini-transaction for x-latching and initializing the
500page
501@param[in] loc debug only parameter providing caller source location.
502@retval NULL if no page could be allocated
503@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
504(init_mtr == mtr, or the page was not previously freed in mtr),
505returned block is not allocated nor initialized otherwise */
506[[nodiscard]] buf_block_t *btr_page_alloc_priv(
507 dict_index_t *index, page_no_t hint_page_no, byte file_direction,
508 ulint level, mtr_t *mtr, mtr_t *init_mtr IF_DEBUG(, const ut::Location &loc)
509
510);
511
512/** Allocates all pages of one extent to be used in an index tree.
513@param[in] index the index for which pages are allocated.
514@param[in] is_leaf true if leaf segment and false if non-leaf segment
515@param[out] page_range All pages within this pair of page numbers are
516allocated for this B-tree. The page_range.first is part of the range, while the
517page_range.second is not part of the range.
518@param[in] mtr mini transaction context for this operation.
519@return DB_SUCCESS on success, error code on failure. */
520[[nodiscard]] dberr_t btr_extent_alloc(const dict_index_t *const index,
521 bool is_leaf, Page_range_t &page_range,
522 mtr_t *mtr);
523
524/** Frees a file page used in an index tree. NOTE: cannot free field external
525 storage pages because the page must contain info on its level. */
526void btr_page_free(dict_index_t *index, /*!< in: index tree */
527 buf_block_t *block, /*!< in: block to be freed, x-latched */
528 mtr_t *mtr); /*!< in: mtr */
529/** Creates a new index page (not the root, and also not
530 used in page reorganization). @see btr_page_empty(). */
531void btr_page_create(
532 buf_block_t *block, /*!< in/out: page to be created */
533 page_zip_des_t *page_zip, /*!< in/out: compressed page, or NULL */
534 dict_index_t *index, /*!< in: index */
535 ulint level, /*!< in: the B-tree level of the page */
536 mtr_t *mtr); /*!< in: mtr */
537
538/** Frees a file page used in an index tree. Can be used also to BLOB
539 external storage pages.
540@param[in] index the index to which the page belongs
541@param[in] block block to be freed, x-latched
542@param[in] level page level (ULINT_UNDEFINED=BLOB)
543@param[in] mtr mini transaction context. */
545 mtr_t *mtr);
546
547/** Gets the root node of a tree and x- or s-latches it.
548 @return root page, x- or s-latched */
550 const dict_index_t *index, /*!< in: index tree */
551 ulint mode, /*!< in: either RW_S_LATCH
552 or RW_X_LATCH */
553 mtr_t *mtr); /*!< in: mtr */
554
555/** Prints size info of a B-tree. */
556void btr_print_size(dict_index_t *index); /*!< in: index tree */
557
558/** Prints directories and other info of all nodes in the index.
559@param[in] index the index to be printed.
560@param[in] width number of entries to print from start and end. */
562
563/** Checks the size and number of fields in a record based on the definition of
564the index.
565 @return true if ok */
566[[nodiscard]] bool btr_index_rec_validate(
567 const rec_t *rec, /*!< in: index record */
568 const dict_index_t *index, /*!< in: index */
569 bool dump_on_error); /*!< in: true if the function
570 should print hex dump of
571 record and page on error */
572/** Checks the consistency of an index tree.
573 @return true if ok */
574[[nodiscard]] bool btr_validate_index(
575 dict_index_t *index, /*!< in: index */
576 const trx_t *trx, /*!< in: transaction or 0 */
577 bool lockout); /*!< in: true if X-latch index is intended */
578
579/** Creates SDI index and stores the root page numbers in page 1 & 2
580@param[in] space_id tablespace id
581@param[in] dict_locked true if dict_sys mutex is acquired
582@return DB_SUCCESS on success, else DB_ERROR on failure */
583dberr_t btr_sdi_create_index(space_id_t space_id, bool dict_locked);
584
585constexpr uint32_t BTR_N_LEAF_PAGES = 1;
586constexpr uint32_t BTR_TOTAL_SIZE = 2;
587
588/** Check if the given index is empty. An index is considered empty if it
589has only the root page with no user records, including del-marked records.
590@param[in] index index
591@return true if index is empty, false otherwise. */
593
594#ifdef UNIV_DEBUG
595/** Does a breadth first traversal (BFT) of the B-tree, and invokes the
596callback for each of the B-tree nodes. */
597struct BFT {
598 struct Callback {
601 size_t m_nrows;
602 size_t m_level;
603 std::ostream &print(std::ostream &out) const;
604 };
605 void init(size_t max_level) { m_data.resize(max_level); }
606 void operator()(buf_block_t *block);
607 std::ostream &print(std::ostream &out) const;
608
609 public:
611
612 private:
613 std::vector<std::list<Page_details>> m_data;
614 };
615 BFT(const dict_index_t *index, Callback &cb);
616 void traverse();
617
618 const dict_index_t *index() const { return m_index; }
619
620 private:
621 void children_to_visit(buf_block_t *block);
623 std::list<page_no_t> m_pages_to_visit;
626};
627
628inline std::ostream &operator<<(std::ostream &out,
629 const BFT::Callback::Page_details &obj) {
630 return obj.print(out);
631}
632
633inline std::ostream &operator<<(std::ostream &out, const BFT::Callback &obj) {
634 return obj.print(out);
635}
636
637#endif /* UNIV_DEBUG */
638
639/** NOTE - Changing this from the original number of 50 to 45 as
640insert_debug.test was failing in ASAN build because of a stack overflow issue.
641It was found that rtr_info_t was taking up a lot of stack space in the function
642btr_insert_on_non_leaf_level_func which is part of the recursive stack
643trace. */
644/** Maximum B-tree page level (not really a hard limit). Used in debug
645 assertions in btr_page_set_level and btr_page_get_level */
646constexpr uint32_t BTR_MAX_NODE_LEVEL = 45;
647#include "btr0btr.ic"
648
649#endif
uint32_t space_id_t
Tablespace identifier.
Definition: api0api.h:49
uint32_t page_no_t
Page number.
Definition: api0api.h:47
bool btr_check_node_ptr(dict_index_t *index, buf_block_t *block, mtr_t *mtr)
Asserts that the node pointer to a page is appropriate.
Definition: btr0btr.cc:3826
constexpr ulint BTR_LATCH_MODE_WITHOUT_FLAGS(ulint latch_mode)
Definition: btr0btr.h:136
bool btr_index_rec_validate(const rec_t *rec, const dict_index_t *index, bool dump_on_error)
Checks the size and number of fields in a record based on the definition of the index.
Definition: btr0btr.cc:3888
std::ostream & operator<<(std::ostream &out, const BFT::Callback::Page_details &obj)
Definition: btr0btr.h:628
ulint btr_create(ulint type, space_id_t space, space_index_t index_id, dict_index_t *index, mtr_t *mtr)
Create the root node for a new index tree.
Definition: btr0btr.cc:860
void btr_truncate(const dict_index_t *index)
Truncate an index tree.
Definition: btr0btr.cc:1078
rec_t * btr_root_raise_and_insert(uint32_t flags, btr_cur_t *cursor, ulint **offsets, mem_heap_t **heap, const dtuple_t *tuple, mtr_t *mtr)
Makes tree one level higher by splitting the root, and inserts the tuple.
Definition: btr0btr.cc:1491
static space_index_t btr_page_get_index_id(const page_t *page)
Gets the index id field of a page.
void btr_free(const page_id_t &page_id, const page_size_t &page_size)
Free an index tree in a temporary tablespace.
Definition: btr0btr.cc:1057
void btr_free_if_exists(const page_id_t &page_id, const page_size_t &page_size, space_index_t index_id, mtr_t *mtr)
Free a persistent index tree if it exists.
Definition: btr0btr.cc:1041
buf_block_t * btr_root_block_get(const dict_index_t *index, ulint mode, mtr_t *mtr)
Gets the root node of a tree and x- or s-latches it.
Definition: btr0btr.cc:165
bool btr_page_reorganize(page_cur_t *cursor, dict_index_t *index, mtr_t *mtr)
Reorganizes an index page.
Definition: btr0btr.cc:1401
static buf_block_t * btr_block_get(const page_id_t &page_id, const page_size_t &page_size, ulint mode, ut::Location location, const dict_index_t *index, mtr_t *mtr)
Gets a buffer page and declares its latching order level.
Definition: btr0btr.h:205
bool btr_validate_index(dict_index_t *index, const trx_t *trx, bool lockout)
Checks the consistency of an index tree.
Definition: btr0btr.cc:4590
btr_latch_mode
Latching modes for btr_cur_search_to_nth_level().
Definition: btr0btr.h:65
@ BTR_CONT_MODIFY_TREE
Continue modifying the entire B-tree.
Definition: btr0btr.h:75
@ BTR_MODIFY_TREE
Start modifying the entire B-tree.
Definition: btr0btr.h:73
@ BTR_MODIFY_LEAF
(Prepare to) modify a record on a leaf page and X-latch it.
Definition: btr0btr.h:69
@ BTR_SEARCH_PREV
Search the previous record.
Definition: btr0btr.h:77
@ BTR_NO_LATCHES
Obtain no latches.
Definition: btr0btr.h:71
@ BTR_SEARCH_LEAF
Search a record on a leaf page and S-latch it.
Definition: btr0btr.h:67
@ BTR_MODIFY_PREV
Modify the previous record.
Definition: btr0btr.h:79
@ BTR_CONT_SEARCH_TREE
Continue searching the entire B-tree.
Definition: btr0btr.h:83
@ BTR_SEARCH_TREE
Start searching the entire B-tree.
Definition: btr0btr.h:81
bool btr_compress(btr_cur_t *cursor, bool adjust, mtr_t *mtr)
Tries to merge the page first to the left immediate brother if such a brother exists,...
Definition: btr0btr.cc:3032
void btr_unset_min_rec_mark(buf_block_t *block, rec_t *rec, mtr_t *mtr)
Removes a record as the predefined minimum record.
Definition: btr0btr.cc:2811
constexpr size_t BTR_IGNORE_SEC_UNIQUE
This flag ORed to BTR_INSERT says that we can ignore possible UNIQUE definition on secondary indexes ...
Definition: btr0btr.h:100
static buf_block_t * btr_block_get_func(const page_id_t &page_id, const page_size_t &page_size, ulint mode, ut::Location location, const dict_index_t *index, mtr_t *mtr)
Gets a buffer page and declares its latching order level.
dberr_t btr_root_adjust_on_import(const dict_index_t *index)
Checks and adjusts the root node of a tree during IMPORT TABLESPACE.
Definition: btr0btr.cc:260
void btr_page_free_low(dict_index_t *index, buf_block_t *block, ulint level, mtr_t *mtr)
Frees a file page used in an index tree.
Definition: btr0btr.cc:552
ulint BTR_LATCH_MODE_WITHOUT_INTENTION(ulint latch_mode)
Definition: btr0btr.h:144
static page_no_t btr_page_get_prev(const page_t *page, mtr_t *mtr)
Gets the previous index page number.
void btr_truncate_recover(const dict_index_t *index)
Recovery function for btr_truncate.
Definition: btr0btr.cc:1134
bool btr_is_index_empty(const dict_index_t *index)
Check if the given index is empty.
Definition: btr0btr.cc:2828
constexpr size_t BTR_RTREE_DELETE_MARK
Try to delete mark the record at the searched position when the record is in spatial index.
Definition: btr0btr.h:132
rec_t * btr_page_split_and_insert(uint32_t flags, btr_cur_t *cursor, ulint **offsets, mem_heap_t **heap, const dtuple_t *tuple, mtr_t *mtr)
Splits an index page to halves and inserts the tuple.
Definition: btr0btr.cc:2314
constexpr size_t BTR_DELETE
Try to purge the record at the searched position using the insert/delete buffer when the record is no...
Definition: btr0btr.h:108
constexpr size_t BTR_LATCH_FOR_DELETE
In the case of BTR_MODIFY_TREE, the caller specifies the intention to delete record only.
Definition: btr0btr.h:120
ulint btr_get_size(dict_index_t *index, ulint flag, mtr_t *mtr)
Gets the number of pages in a B-tree.
Definition: btr0btr.cc:490
void btr_print_size(dict_index_t *index)
Prints size info of a B-tree.
constexpr size_t BTR_DELETE_MARK
Try to delete mark the record at the searched position using the insert/delete buffer when the record...
Definition: btr0btr.h:104
constexpr size_t BTR_INSERT
If this is ORed to btr_latch_mode, it means that the search tuple will be inserted to the index,...
Definition: btr0btr.h:91
buf_block_t * btr_node_ptr_get_child(const rec_t *node_ptr, dict_index_t *index, const ulint *offsets, mtr_t *mtr, rw_lock_type_t type=RW_SX_LATCH)
Returns the child page of a node pointer and sx-latches it.
Definition: btr0btr.cc:640
constexpr size_t BTR_ALREADY_S_LATCHED
In the case of BTR_SEARCH_LEAF or BTR_MODIFY_LEAF, the caller is already holding an S latch on the in...
Definition: btr0btr.h:112
const byte * btr_parse_set_min_rec_mark(const byte *ptr, const byte *end_ptr, ulint comp, page_t *page, mtr_t *mtr)
Parses the redo log record for setting an index record as the predefined minimum record.
Definition: btr0btr.cc:2765
constexpr size_t BTR_ESTIMATE
This flag ORed to btr_latch_mode says that we do the search in query optimization.
Definition: btr0btr.h:95
void btr_node_ptr_delete(dict_index_t *index, buf_block_t *block, mtr_t *mtr)
Deletes on the upper level the node pointer to a page.
Definition: btr0btr.cc:2843
void btr_print_index(dict_index_t *index, ulint width)
Prints directories and other info of all nodes in the index.
static page_no_t btr_page_get_next(const page_t *page, mtr_t *mtr)
Gets the next index page number.
static ulint btr_page_get_level(const page_t *page)
Gets the node level field in an index page.
bool btr_page_get_split_rec_to_left(btr_cur_t *cursor, rec_t **split_rec)
Decides if the page should be split at the convergence point of inserts converging to left.
Definition: btr0btr.cc:1674
bool btr_page_reorganize_low(bool recovery, ulint z_level, page_cur_t *cursor, dict_index_t *index, mtr_t *mtr)
Reorganizes an index page.
Definition: btr0btr.cc:1172
constexpr size_t BTR_RTREE_UNDO_INS
This flag is for undo insert of rtree.
Definition: btr0btr.h:124
buf_block_t * btr_page_alloc_priv(dict_index_t *index, page_no_t hint_page_no, byte file_direction, ulint level, mtr_t *mtr, mtr_t *init_mtr, const ut::Location &loc)
Allocates a new file page to be used in an index tree.
Definition: btr0btr.cc:468
void btr_insert_on_non_leaf_level(uint32_t flags, dict_index_t *index, ulint level, dtuple_t *tuple, ut::Location location, mtr_t *mtr)
Inserts a data tuple to a tree on a non-leaf level.
Definition: btr0btr.cc:1961
std::pair< page_no_t, page_no_t > Page_range_t
Definition: btr0btr.h:134
void btr_page_create(buf_block_t *block, page_zip_des_t *page_zip, dict_index_t *index, ulint level, mtr_t *mtr)
Creates a new index page (not the root, and also not used in page reorganization).
Definition: btr0btr.cc:332
dberr_t btr_sdi_create_index(space_id_t space_id, bool dict_locked)
Creates SDI index and stores the root page numbers in page 1 & 2.
Definition: btr0btr.cc:4771
constexpr uint32_t BTR_MAX_LEVELS
Maximum depth of a B-tree in InnoDB.
Definition: btr0btr.h:59
constexpr size_t BTR_MODIFY_EXTERNAL
In the case of BTR_MODIFY_LEAF, the caller intends to allocate or free the pages of externally stored...
Definition: btr0btr.h:128
constexpr uint32_t BTR_N_LEAF_PAGES
Definition: btr0btr.h:585
constexpr uint32_t BTR_TOTAL_SIZE
Definition: btr0btr.h:586
void btr_set_min_rec_mark(rec_t *rec, mtr_t *mtr)
Sets a record as the predefined minimum record.
Definition: btr0btr.cc:2793
page_t * btr_root_get(const dict_index_t *index, mtr_t *mtr)
Gets the root node of a tree and sx-latches it for segment access.
Definition: btr0btr.cc:195
constexpr space_index_t BTR_FREED_INDEX_ID
PAGE_INDEX_ID value for freed index B-trees.
Definition: btr0btr.h:62
constexpr uint32_t BTR_MAX_NODE_LEVEL
NOTE - Changing this from the original number of 50 to 45 as insert_debug.test was failing in ASAN bu...
Definition: btr0btr.h:646
void btr_discard_page(btr_cur_t *cursor, mtr_t *mtr)
Discards a page from a B-tree.
Definition: btr0btr.cc:3567
void btr_corruption_report(const buf_block_t *block, const dict_index_t *index) UNIV_COLD
Report that an index page is corrupted.
Definition: btr0btr.cc:83
constexpr size_t BTR_LATCH_FOR_INSERT
In the case of BTR_MODIFY_TREE, the caller specifies the intention to insert record only.
Definition: btr0btr.h:116
static page_no_t btr_node_ptr_get_child_page_no(const rec_t *rec, const ulint *offsets)
Gets the child node file address in a node pointer.
dberr_t btr_extent_alloc(const dict_index_t *const index, bool is_leaf, Page_range_t &page_range, mtr_t *mtr)
Allocates all pages of one extent to be used in an index tree.
Definition: btr0btr.cc:454
void btr_assert_not_corrupted(const buf_block_t *block, const dict_index_t *index)
Assert that a B-tree page is not corrupted.
Definition: btr0btr.h:157
const byte * btr_parse_page_reorganize(const byte *ptr, const byte *end_ptr, dict_index_t *index, bool compressed, buf_block_t *block, mtr_t *mtr)
Parses a redo log record of reorganizing a page.
Definition: btr0btr.cc:1407
void btr_page_free(dict_index_t *index, buf_block_t *block, mtr_t *mtr)
Frees a file page used in an index tree.
Definition: btr0btr.cc:598
bool btr_page_get_split_rec_to_right(btr_cur_t *cursor, rec_t **split_rec)
Decides if the page should be split at the convergence point of inserts converging to right.
Definition: btr0btr.cc:1712
ulint btr_height_get(dict_index_t *index, mtr_t *mtr)
Gets the height of the B-tree (the level of the root, when the leaf level is assumed to be 0).
Definition: btr0btr.cc:208
static void btr_leaf_page_release(buf_block_t *block, ulint latch_mode, mtr_t *mtr)
Releases the latch on a leaf page and bufferunfixes it.
The B-tree.
The index tree general types.
static buf_frame_t * buf_block_get_frame(const buf_block_t *block)
Gets a pointer to the memory frame of a block.
Page identifier.
Definition: buf0types.h:191
Page size descriptor.
Definition: page0size.h:50
int page
Definition: ctype-mb.cc:1226
SQL data field and tuple.
dberr_t
Definition: db0err.h:39
Data dictionary system.
static bool dict_table_is_comp(const dict_table_t *table)
Check whether the table uses the compact page format.
ib_id_t space_index_t
Index identifier (unique within a tablespace).
Definition: dict0types.h:218
R-tree header file.
static int flags[50]
Definition: hp_test1.cc:40
static int flag
Definition: hp_test1.cc:40
Mini-transaction buffer.
static PFS_engine_table_share_proxy table
Definition: pfs.cc:61
static bool cb(unsigned long long new_value)
Definition: option_usage.cc:45
bool index(const std::string &value, const String &search_for, uint32_t *idx)
Definition: contains.h:76
mode
Definition: file_handle.h:61
The page cursor.
static bool page_is_comp(const page_t *page)
Determine whether the page is in new-style compact format.
byte page_t
Type of the index page.
Definition: page0types.h:152
byte rec_t
Definition: rem0types.h:41
required string type
Definition: replication_group_member_actions.proto:34
Definition: btr0btr.h:599
size_t m_level
Definition: btr0btr.h:602
std::ostream & print(std::ostream &out) const
Definition: btr0btr.cc:4836
page_no_t m_page_no
Definition: btr0btr.h:600
size_t m_nrows
Definition: btr0btr.h:601
Definition: btr0btr.h:598
std::ostream & print(std::ostream &out) const
Definition: btr0btr.cc:4842
BFT * m_bft
Definition: btr0btr.h:610
std::vector< std::list< Page_details > > m_data
Definition: btr0btr.h:613
void operator()(buf_block_t *block)
Definition: btr0btr.cc:4918
void init(size_t max_level)
Definition: btr0btr.h:605
Does a breadth first traversal (BFT) of the B-tree, and invokes the callback for each of the B-tree n...
Definition: btr0btr.h:597
std::list< page_no_t > m_pages_to_visit
Definition: btr0btr.h:623
void children_to_visit(buf_block_t *block)
Definition: btr0btr.cc:4882
const dict_index_t * m_index
Definition: btr0btr.h:624
void traverse()
Definition: btr0btr.cc:4902
page_no_t visit_next()
Definition: btr0btr.cc:4873
const dict_index_t * index() const
Definition: btr0btr.h:618
BFT(const dict_index_t *index, Callback &cb)
Definition: btr0btr.cc:4866
Callback & m_callback
Definition: btr0btr.h:625
The tree cursor: the definition appears here only for the compiler to know struct size!
Definition: btr0cur.h:668
The buffer control block structure.
Definition: buf0buf.h:1756
Data structure for an index.
Definition: dict0mem.h:1069
Structure for an SQL data tuple of fields (logical record)
Definition: data0data.h:706
The info structure stored at the beginning of a heap block.
Definition: mem0mem.h:295
Mini-transaction handle and buffer.
Definition: mtr0mtr.h:174
Index page cursor.
Definition: page0cur.h:311
Compressed page descriptor.
Definition: page0types.h:201
Definition: trx0trx.h:670
Definition: ut0core.h:36
rw_lock_type_t
Definition: sync0rw.h:96
@ RW_SX_LATCH
Definition: sync0rw.h:99
@ RW_NO_LATCH
Definition: sync0rw.h:100
@ RW_X_LATCH
Definition: sync0rw.h:98
@ RW_S_LATCH
Definition: sync0rw.h:97
Version control for database, common definitions, and include files.
#define UNIV_COLD
Definition: univ.i:264
#define IF_DEBUG(...)
Definition: univ.i:677
unsigned long int ulint
Definition: univ.i:403
#define ut_error
Abort execution.
Definition: ut0dbg.h:105