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