1 /***************************************************************************** 2 3 Copyright (c) 1997, 2021, Oracle and/or its affiliates. 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 @return DB_SUCCESS or failure */ 104 dberr_t 105 ibuf_init_at_db_start(void); 106 /*=======================*/ 107 /*********************************************************************//** 108 Updates the max_size value for ibuf. */ 109 void 110 ibuf_max_size_update( 111 /*=================*/ 112 ulint new_val); /*!< in: new value in terms of 113 percentage of the buffer pool size */ 114 /*********************************************************************//** 115 Reads the biggest tablespace id from the high end of the insert buffer 116 tree and updates the counter in fil_system. */ 117 void 118 ibuf_update_max_tablespace_id(void); 119 /*===============================*/ 120 /***************************************************************//** 121 Starts an insert buffer mini-transaction. */ 122 UNIV_INLINE 123 void 124 ibuf_mtr_start( 125 /*===========*/ 126 mtr_t* mtr) /*!< out: mini-transaction */ 127 MY_ATTRIBUTE((nonnull)); 128 /***************************************************************//** 129 Commits an insert buffer mini-transaction. */ 130 UNIV_INLINE 131 void 132 ibuf_mtr_commit( 133 /*============*/ 134 mtr_t* mtr) /*!< in/out: mini-transaction */ 135 MY_ATTRIBUTE((nonnull)); 136 /*********************************************************************//** 137 Initializes an ibuf bitmap page. */ 138 void 139 ibuf_bitmap_page_init( 140 /*==================*/ 141 buf_block_t* block, /*!< in: bitmap page */ 142 mtr_t* mtr); /*!< in: mtr */ 143 /************************************************************************//** 144 Resets the free bits of the page in the ibuf bitmap. This is done in a 145 separate mini-transaction, hence this operation does not restrict 146 further work to only ibuf bitmap operations, which would result if the 147 latch to the bitmap page were kept. NOTE: The free bits in the insert 148 buffer bitmap must never exceed the free space on a page. It is safe 149 to decrement or reset the bits in the bitmap in a mini-transaction 150 that is committed before the mini-transaction that affects the free 151 space. */ 152 void 153 ibuf_reset_free_bits( 154 /*=================*/ 155 buf_block_t* block); /*!< in: index page; free bits are set to 0 156 if the index is a non-clustered 157 non-unique, and page level is 0 */ 158 /************************************************************************//** 159 Updates the free bits of an uncompressed page in the ibuf bitmap if 160 there is not enough free on the page any more. This is done in a 161 separate mini-transaction, hence this operation does not restrict 162 further work to only ibuf bitmap operations, which would result if the 163 latch to the bitmap page were kept. NOTE: The free bits in the insert 164 buffer bitmap must never exceed the free space on a page. It is 165 unsafe to increment the bits in a separately committed 166 mini-transaction, because in crash recovery, the free bits could 167 momentarily be set too high. It is only safe to use this function for 168 decrementing the free bits. Should more free space become available, 169 we must not update the free bits here, because that would break crash 170 recovery. */ 171 UNIV_INLINE 172 void 173 ibuf_update_free_bits_if_full( 174 /*==========================*/ 175 buf_block_t* block, /*!< in: index page to which we have added new 176 records; the free bits are updated if the 177 index is non-clustered and non-unique and 178 the page level is 0, and the page becomes 179 fuller */ 180 ulint max_ins_size,/*!< in: value of maximum insert size with 181 reorganize before the latest operation 182 performed to the page */ 183 ulint increase);/*!< in: upper limit for the additional space 184 used in the latest operation, if known, or 185 ULINT_UNDEFINED */ 186 /**********************************************************************//** 187 Updates the free bits for an uncompressed page to reflect the present 188 state. Does this in the mtr given, which means that the latching 189 order rules virtually prevent any further operations for this OS 190 thread until mtr is committed. NOTE: The free bits in the insert 191 buffer bitmap must never exceed the free space on a page. It is safe 192 to set the free bits in the same mini-transaction that updated the 193 page. */ 194 void 195 ibuf_update_free_bits_low( 196 /*======================*/ 197 const buf_block_t* block, /*!< in: index page */ 198 ulint max_ins_size, /*!< in: value of 199 maximum insert size 200 with reorganize before 201 the latest operation 202 performed to the page */ 203 mtr_t* mtr); /*!< in/out: mtr */ 204 /**********************************************************************//** 205 Updates the free bits for a compressed page to reflect the present 206 state. Does this in the mtr given, which means that the latching 207 order rules virtually prevent any further operations for this OS 208 thread until mtr is committed. NOTE: The free bits in the insert 209 buffer bitmap must never exceed the free space on a page. It is safe 210 to set the free bits in the same mini-transaction that updated the 211 page. */ 212 void 213 ibuf_update_free_bits_zip( 214 /*======================*/ 215 buf_block_t* block, /*!< in/out: index page */ 216 mtr_t* mtr); /*!< in/out: mtr */ 217 /**********************************************************************//** 218 Updates the free bits for the two pages to reflect the present state. 219 Does this in the mtr given, which means that the latching order rules 220 virtually prevent any further operations until mtr is committed. 221 NOTE: The free bits in the insert buffer bitmap must never exceed the 222 free space on a page. It is safe to set the free bits in the same 223 mini-transaction that updated the pages. */ 224 void 225 ibuf_update_free_bits_for_two_pages_low( 226 /*====================================*/ 227 buf_block_t* block1, /*!< in: index page */ 228 buf_block_t* block2, /*!< in: index page */ 229 mtr_t* mtr); /*!< in: mtr */ 230 /**********************************************************************//** 231 A basic partial test if an insert to the insert buffer could be possible and 232 recommended. */ 233 UNIV_INLINE 234 ibool 235 ibuf_should_try( 236 /*============*/ 237 dict_index_t* index, /*!< in: index where to insert */ 238 ulint ignore_sec_unique); /*!< in: if != 0, we should 239 ignore UNIQUE constraint on 240 a secondary index when we 241 decide */ 242 /******************************************************************//** 243 Returns TRUE if the current OS thread is performing an insert buffer 244 routine. 245 246 For instance, a read-ahead of non-ibuf pages is forbidden by threads 247 that are executing an insert buffer routine. 248 @return TRUE if inside an insert buffer routine */ 249 UNIV_INLINE 250 ibool 251 ibuf_inside( 252 /*========*/ 253 const mtr_t* mtr) /*!< in: mini-transaction */ 254 MY_ATTRIBUTE((warn_unused_result)); 255 256 /** Checks if a page address is an ibuf bitmap page (level 3 page) address. 257 @param[in] page_id page id 258 @param[in] page_size page size 259 @return TRUE if a bitmap page */ 260 UNIV_INLINE 261 ibool 262 ibuf_bitmap_page( 263 const page_id_t& page_id, 264 const page_size_t& page_size); 265 266 /** Checks if a page is a level 2 or 3 page in the ibuf hierarchy of pages. 267 Must not be called when recv_no_ibuf_operations==true. 268 @param[in] page_id page id 269 @param[in] page_size page size 270 @param[in] x_latch FALSE if relaxed check (avoid latching the 271 bitmap page) 272 @param[in] file file name 273 @param[in] line line where called 274 @param[in,out] mtr mtr which will contain an x-latch to the 275 bitmap page if the page is not one of the fixed address ibuf pages, or NULL, 276 in which case a new transaction is created. 277 @return TRUE if level 2 or level 3 page */ 278 ibool 279 ibuf_page_low( 280 const page_id_t& page_id, 281 const page_size_t& page_size, 282 #ifdef UNIV_DEBUG 283 ibool x_latch, 284 #endif /* UNIV_DEBUG */ 285 const char* file, 286 ulint line, 287 mtr_t* mtr) 288 MY_ATTRIBUTE((warn_unused_result)); 289 290 #ifdef UNIV_DEBUG 291 292 /** Checks if a page is a level 2 or 3 page in the ibuf hierarchy of pages. 293 Must not be called when recv_no_ibuf_operations==true. 294 @param[in] page_id tablespace/page identifier 295 @param[in] page_size page size 296 @param[in,out] mtr mini-transaction or NULL 297 @return TRUE if level 2 or level 3 page */ 298 # define ibuf_page(page_id, page_size, mtr) \ 299 ibuf_page_low(page_id, page_size, TRUE, __FILE__, __LINE__, mtr) 300 301 #else /* UVIV_DEBUG */ 302 303 /** Checks if a page is a level 2 or 3 page in the ibuf hierarchy of pages. 304 Must not be called when recv_no_ibuf_operations==true. 305 @param[in] page_id tablespace/page identifier 306 @param[in] page_size page size 307 @param[in,out] mtr mini-transaction or NULL 308 @return TRUE if level 2 or level 3 page */ 309 # define ibuf_page(page_id, page_size, mtr) \ 310 ibuf_page_low(page_id, page_size, __FILE__, __LINE__, mtr) 311 312 #endif /* UVIV_DEBUG */ 313 /***********************************************************************//** 314 Frees excess pages from the ibuf free list. This function is called when an OS 315 thread calls fsp services to allocate a new file segment, or a new page to a 316 file segment, and the thread did not own the fsp latch before this call. */ 317 void 318 ibuf_free_excess_pages(void); 319 /*========================*/ 320 321 /** Buffer an operation in the insert/delete buffer, instead of doing it 322 directly to the disk page, if this is possible. Does not do it if the index 323 is clustered or unique. 324 @param[in] op operation type 325 @param[in] entry index entry to insert 326 @param[in,out] index index where to insert 327 @param[in] page_id page id where to insert 328 @param[in] page_size page size 329 @param[in,out] thr query thread 330 @return TRUE if success */ 331 ibool 332 ibuf_insert( 333 ibuf_op_t op, 334 const dtuple_t* entry, 335 dict_index_t* index, 336 const page_id_t& page_id, 337 const page_size_t& page_size, 338 que_thr_t* thr); 339 340 /** When an index page is read from a disk to the buffer pool, this function 341 applies any buffered operations to the page and deletes the entries from the 342 insert buffer. If the page is not read, but created in the buffer pool, this 343 function deletes its buffered entries from the insert buffer; there can 344 exist entries for such a page if the page belonged to an index which 345 subsequently was dropped. 346 @param[in,out] block if page has been read from disk, 347 pointer to the page x-latched, else NULL 348 @param[in] page_id page id of the index page 349 @param[in] update_ibuf_bitmap normally this is set to TRUE, but 350 if we have deleted or are deleting the tablespace, then we naturally do not 351 want to update a non-existent bitmap page */ 352 void 353 ibuf_merge_or_delete_for_page( 354 buf_block_t* block, 355 const page_id_t& page_id, 356 const page_size_t* page_size, 357 ibool update_ibuf_bitmap); 358 359 /*********************************************************************//** 360 Deletes all entries in the insert buffer for a given space id. This is used 361 in DISCARD TABLESPACE and IMPORT TABLESPACE. 362 NOTE: this does not update the page free bitmaps in the space. The space will 363 become CORRUPT when you call this function! */ 364 void 365 ibuf_delete_for_discarded_space( 366 /*============================*/ 367 ulint space); /*!< in: space id */ 368 /** Contract the change buffer by reading pages to the buffer pool. 369 @param[in] full If true, do a full contraction based 370 on PCT_IO(100). If false, the size of contract batch is determined 371 based on the current size of the change buffer. 372 @return a lower limit for the combined size in bytes of entries which 373 will be merged from ibuf trees to the pages read, 0 if ibuf is 374 empty */ 375 ulint 376 ibuf_merge_in_background( 377 bool full); 378 379 /** Contracts insert buffer trees by reading pages referring to space_id 380 to the buffer pool. 381 @returns number of pages merged.*/ 382 ulint 383 ibuf_merge_space( 384 /*=============*/ 385 ulint space); /*!< in: space id */ 386 387 #endif /* !UNIV_HOTBACKUP */ 388 /*********************************************************************//** 389 Parses a redo log record of an ibuf bitmap page init. 390 @return end of log record or NULL */ 391 byte* 392 ibuf_parse_bitmap_init( 393 /*===================*/ 394 byte* ptr, /*!< in: buffer */ 395 byte* end_ptr,/*!< in: buffer end */ 396 buf_block_t* block, /*!< in: block or NULL */ 397 mtr_t* mtr); /*!< in: mtr or NULL */ 398 #ifndef UNIV_HOTBACKUP 399 #ifdef UNIV_IBUF_COUNT_DEBUG 400 401 /** Gets the ibuf count for a given page. 402 @param[in] page_id page id 403 @return number of entries in the insert buffer currently buffered for 404 this page */ 405 ulint 406 ibuf_count_get( 407 const page_id_t& page_id); 408 409 #endif 410 /******************************************************************//** 411 Looks if the insert buffer is empty. 412 @return true if empty */ 413 bool 414 ibuf_is_empty(void); 415 /*===============*/ 416 /******************************************************************//** 417 Prints info of ibuf. */ 418 void 419 ibuf_print( 420 /*=======*/ 421 FILE* file); /*!< in: file where to print */ 422 /******************************************************************** 423 Read the first two bytes from a record's fourth field (counter field in new 424 records; something else in older records). 425 @return "counter" field, or ULINT_UNDEFINED if for some reason it can't be read */ 426 ulint 427 ibuf_rec_get_counter( 428 /*=================*/ 429 const rec_t* rec); /*!< in: ibuf record */ 430 /******************************************************************//** 431 Closes insert buffer and frees the data structures. */ 432 void 433 ibuf_close(void); 434 /*============*/ 435 /******************************************************************//** 436 Function to pass ibuf status variables */ 437 438 void 439 ibuf_export_ibuf_status( 440 /*====================*/ 441 ulint* free_list, 442 ulint* segment_size); 443 444 /******************************************************************//** 445 Checks the insert buffer bitmaps on IMPORT TABLESPACE. 446 @return DB_SUCCESS or error code */ 447 dberr_t 448 ibuf_check_bitmap_on_import( 449 /*========================*/ 450 const trx_t* trx, /*!< in: transaction */ 451 ulint space_id) /*!< in: tablespace identifier */ 452 MY_ATTRIBUTE((nonnull, warn_unused_result)); 453 454 /** Updates free bits and buffered bits for bulk loaded page. 455 @param[in] block index page 456 @param]in] reset flag if reset free val */ 457 void 458 ibuf_set_bitmap_for_bulk_load( 459 buf_block_t* block, 460 bool reset); 461 462 #define IBUF_HEADER_PAGE_NO FSP_IBUF_HEADER_PAGE_NO 463 #define IBUF_TREE_ROOT_PAGE_NO FSP_IBUF_TREE_ROOT_PAGE_NO 464 465 #endif /* !UNIV_HOTBACKUP */ 466 467 /* The ibuf header page currently contains only the file segment header 468 for the file segment from which the pages for the ibuf tree are allocated */ 469 #define IBUF_HEADER PAGE_DATA 470 #define IBUF_TREE_SEG_HEADER 0 /* fseg header for ibuf tree */ 471 472 /* The insert buffer tree itself is always located in space 0. */ 473 #define IBUF_SPACE_ID static_cast<ulint>(0) 474 475 #ifndef UNIV_NONINL 476 #include "ibuf0ibuf.ic" 477 #endif 478 479 #endif 480