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