1 /***************************************************************************** 2 3 Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. 4 Copyright (c) 2013, 2022, MariaDB Corporation. 5 6 This program is free software; you can redistribute it and/or modify it under 7 the terms of the GNU General Public License as published by the Free Software 8 Foundation; version 2 of the License. 9 10 This program is distributed in the hope that it will be useful, but WITHOUT 11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License along with 15 this program; if not, write to the Free Software Foundation, Inc., 16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA 17 18 *****************************************************************************/ 19 20 /**************************************************//** 21 @file include/mtr0mtr.h 22 Mini-transaction buffer 23 24 Created 11/26/1995 Heikki Tuuri 25 *******************************************************/ 26 27 #ifndef mtr0mtr_h 28 #define mtr0mtr_h 29 30 #include "fil0fil.h" 31 #include "dyn0buf.h" 32 33 /** Start a mini-transaction. */ 34 #define mtr_start(m) (m)->start() 35 36 /** Commit a mini-transaction. */ 37 #define mtr_commit(m) (m)->commit() 38 39 /** Set and return a savepoint in mtr. 40 @return savepoint */ 41 #define mtr_set_savepoint(m) (m)->get_savepoint() 42 43 /** Release the (index tree) s-latch stored in an mtr memo after a 44 savepoint. */ 45 #define mtr_release_s_latch_at_savepoint(m, s, l) \ 46 (m)->release_s_latch_at_savepoint((s), (l)) 47 48 /** Change the logging mode of a mini-transaction. 49 @return old mode */ 50 #define mtr_set_log_mode(m, d) (m)->set_log_mode((d)) 51 52 /** Release an object in the memo stack. 53 @return true if released */ 54 #define mtr_memo_release(m, o, t) \ 55 (m)->memo_release((o), (t)) 56 57 /** Print info of an mtr handle. */ 58 #define mtr_print(m) (m)->print() 59 60 /** Return the log object of a mini-transaction buffer. 61 @return log */ 62 #define mtr_get_log(m) (m)->get_log() 63 64 /** Push an object to an mtr memo stack. */ 65 #define mtr_memo_push(m, o, t) (m)->memo_push(o, t) 66 67 #define mtr_x_lock_space(s, m) (m)->x_lock_space((s), __FILE__, __LINE__) 68 #define mtr_sx_lock_space(s, m) (m)->sx_lock_space((s), __FILE__, __LINE__) 69 70 #define mtr_s_lock_index(i, m) (m)->s_lock(&(i)->lock, __FILE__, __LINE__) 71 #define mtr_x_lock_index(i, m) (m)->x_lock(&(i)->lock, __FILE__, __LINE__) 72 #define mtr_sx_lock_index(i, m) (m)->sx_lock(&(i)->lock, __FILE__, __LINE__) 73 74 #define mtr_release_block_at_savepoint(m, s, b) \ 75 (m)->release_block_at_savepoint((s), (b)) 76 77 #define mtr_block_sx_latch_at_savepoint(m, s, b) \ 78 (m)->sx_latch_at_savepoint((s), (b)) 79 80 #define mtr_block_x_latch_at_savepoint(m, s, b) \ 81 (m)->x_latch_at_savepoint((s), (b)) 82 83 /** Mini-transaction memo stack slot. */ 84 struct mtr_memo_slot_t { 85 /** pointer to the object */ 86 void* object; 87 88 /** type of the stored object */ 89 mtr_memo_type_t type; 90 }; 91 92 /** Mini-transaction handle and buffer */ 93 struct mtr_t { 94 /** Start a mini-transaction. */ 95 void start(); 96 97 /** Commit the mini-transaction. */ 98 void commit(); 99 100 /** Commit a mini-transaction that is shrinking a tablespace. 101 @param space tablespace that is being shrunk */ 102 ATTRIBUTE_COLD void commit_shrink(fil_space_t &space); 103 104 /** Commit a mini-transaction that did not modify any pages, 105 but generated some redo log on a higher level, such as 106 FILE_MODIFY records and an optional FILE_CHECKPOINT marker. 107 The caller must hold log_sys.mutex. 108 This is to be used at log_checkpoint(). 109 @param checkpoint_lsn the log sequence number of a checkpoint, or 0 */ 110 void commit_files(lsn_t checkpoint_lsn= 0); 111 112 /** @return mini-transaction savepoint (current size of m_memo) */ get_savepointmtr_t113 ulint get_savepoint() const { ut_ad(is_active()); return m_memo.size(); } 114 115 /** Release the (index tree) s-latch stored in an mtr memo after a 116 savepoint. 117 @param savepoint value returned by @see set_savepoint. 118 @param lock latch to release */ 119 inline void release_s_latch_at_savepoint( 120 ulint savepoint, 121 rw_lock_t* lock); 122 123 /** Release the block in an mtr memo after a savepoint. */ 124 inline void release_block_at_savepoint( 125 ulint savepoint, 126 buf_block_t* block); 127 128 /** SX-latch a not yet latched block after a savepoint. */ 129 inline void sx_latch_at_savepoint(ulint savepoint, buf_block_t* block); 130 131 /** X-latch a not yet latched block after a savepoint. */ 132 inline void x_latch_at_savepoint(ulint savepoint, buf_block_t* block); 133 134 /** @return the logging mode */ get_log_modemtr_t135 mtr_log_t get_log_mode() const 136 { 137 static_assert(MTR_LOG_ALL == 0, "efficiency"); 138 ut_ad(m_log_mode <= MTR_LOG_NO_REDO); 139 return static_cast<mtr_log_t>(m_log_mode); 140 } 141 142 /** Change the logging mode. 143 @param mode logging mode 144 @return old mode */ set_log_modemtr_t145 mtr_log_t set_log_mode(mtr_log_t mode) 146 { 147 const mtr_log_t old_mode= get_log_mode(); 148 m_log_mode= mode & 3; 149 return old_mode; 150 } 151 152 /** Check if we are holding a block latch in exclusive mode 153 @param block buffer pool block to search for */ 154 bool have_x_latch(const buf_block_t &block) const; 155 156 /** Copy the tablespaces associated with the mini-transaction 157 (needed for generating FILE_MODIFY records) 158 @param[in] mtr mini-transaction that may modify 159 the same set of tablespaces as this one */ set_spacesmtr_t160 void set_spaces(const mtr_t& mtr) 161 { 162 ut_ad(!m_user_space_id); 163 ut_ad(!m_user_space); 164 165 ut_d(m_user_space_id = mtr.m_user_space_id); 166 m_user_space = mtr.m_user_space; 167 } 168 169 /** Set the tablespace associated with the mini-transaction 170 (needed for generating a FILE_MODIFY record) 171 @param[in] space_id user or system tablespace ID 172 @return the tablespace */ set_named_space_idmtr_t173 fil_space_t* set_named_space_id(ulint space_id) 174 { 175 ut_ad(!m_user_space_id); 176 ut_d(m_user_space_id = static_cast<uint32_t>(space_id)); 177 if (!space_id) { 178 return fil_system.sys_space; 179 } else { 180 ut_ad(m_user_space_id == space_id); 181 ut_ad(!m_user_space); 182 m_user_space = fil_space_get(space_id); 183 ut_ad(m_user_space); 184 return m_user_space; 185 } 186 } 187 188 /** Set the tablespace associated with the mini-transaction 189 (needed for generating a FILE_MODIFY record) 190 @param[in] space user or system tablespace */ set_named_spacemtr_t191 void set_named_space(fil_space_t* space) 192 { 193 ut_ad(!m_user_space_id); 194 ut_d(m_user_space_id = static_cast<uint32_t>(space->id)); 195 if (space->id) { 196 m_user_space = space; 197 } 198 } 199 200 #ifdef UNIV_DEBUG 201 /** Check the tablespace associated with the mini-transaction 202 (needed for generating a FILE_MODIFY record) 203 @param[in] space tablespace 204 @return whether the mini-transaction is associated with the space */ 205 bool is_named_space(ulint space) const; 206 /** Check the tablespace associated with the mini-transaction 207 (needed for generating a FILE_MODIFY record) 208 @param[in] space tablespace 209 @return whether the mini-transaction is associated with the space */ 210 bool is_named_space(const fil_space_t* space) const; 211 #endif /* UNIV_DEBUG */ 212 213 /** Acquire a tablespace X-latch. 214 @param[in] space_id tablespace ID 215 @param[in] file file name from where called 216 @param[in] line line number in file 217 @return the tablespace object (never NULL) */ 218 fil_space_t* x_lock_space( 219 ulint space_id, 220 const char* file, 221 unsigned line); 222 223 /** Acquire a shared rw-latch. 224 @param[in] lock rw-latch 225 @param[in] file file name from where called 226 @param[in] line line number in file */ s_lockmtr_t227 void s_lock(rw_lock_t* lock, const char* file, unsigned line) 228 { 229 rw_lock_s_lock_inline(lock, 0, file, line); 230 memo_push(lock, MTR_MEMO_S_LOCK); 231 } 232 233 /** Acquire an exclusive rw-latch. 234 @param[in] lock rw-latch 235 @param[in] file file name from where called 236 @param[in] line line number in file */ x_lockmtr_t237 void x_lock(rw_lock_t* lock, const char* file, unsigned line) 238 { 239 rw_lock_x_lock_inline(lock, 0, file, line); 240 memo_push(lock, MTR_MEMO_X_LOCK); 241 } 242 243 /** Acquire an shared/exclusive rw-latch. 244 @param[in] lock rw-latch 245 @param[in] file file name from where called 246 @param[in] line line number in file */ sx_lockmtr_t247 void sx_lock(rw_lock_t* lock, const char* file, unsigned line) 248 { 249 rw_lock_sx_lock_inline(lock, 0, file, line); 250 memo_push(lock, MTR_MEMO_SX_LOCK); 251 } 252 253 /** Acquire a tablespace X-latch. 254 @param[in] space tablespace 255 @param[in] file file name from where called 256 @param[in] line line number in file */ x_lock_spacemtr_t257 void x_lock_space(fil_space_t* space, const char* file, unsigned line) 258 { 259 ut_ad(space->purpose == FIL_TYPE_TEMPORARY 260 || space->purpose == FIL_TYPE_IMPORT 261 || space->purpose == FIL_TYPE_TABLESPACE); 262 memo_push(space, MTR_MEMO_SPACE_X_LOCK); 263 rw_lock_x_lock_inline(&space->latch, 0, file, line); 264 } 265 266 /** Acquire a tablespace SX-latch. 267 @param[in] space tablespace 268 @param[in] file file name from where called 269 @param[in] line line number in file */ sx_lock_spacemtr_t270 void sx_lock_space(fil_space_t *space, const char *file, unsigned line) 271 { 272 ut_ad(space->purpose == FIL_TYPE_TEMPORARY 273 || space->purpose == FIL_TYPE_IMPORT 274 || space->purpose == FIL_TYPE_TABLESPACE); 275 sx_lock(&space->latch, file, line); 276 } 277 278 /** Release an object in the memo stack. 279 @param object object 280 @param type object type 281 @return bool if lock released */ 282 bool memo_release(const void* object, ulint type); 283 /** Release a page latch. 284 @param[in] ptr pointer to within a page frame 285 @param[in] type object type: MTR_MEMO_PAGE_X_FIX, ... */ 286 void release_page(const void* ptr, mtr_memo_type_t type); 287 288 private: 289 /** Note that the mini-transaction will modify data. */ flag_modifiedmtr_t290 void flag_modified() { m_modifications = true; } 291 /** Mark the given latched page as modified. 292 @param block page that will be modified */ 293 void modify(const buf_block_t& block); 294 public: 295 /** Note that the mini-transaction will modify a block. */ set_modifiedmtr_t296 void set_modified(const buf_block_t &block) 297 { flag_modified(); if (m_log_mode != MTR_LOG_NONE) modify(block); } 298 299 /** Set the state to not-modified. This will not log the changes. 300 This is only used during redo log apply, to avoid logging the changes. */ discard_modificationsmtr_t301 void discard_modifications() { m_modifications = false; } 302 303 /** Get the LSN of commit(). 304 @return the commit LSN 305 @retval 0 if the transaction only modified temporary tablespaces */ commit_lsnmtr_t306 lsn_t commit_lsn() const { ut_ad(has_committed()); return m_commit_lsn; } 307 308 /** Note that we are inside the change buffer code. */ enter_ibufmtr_t309 void enter_ibuf() { m_inside_ibuf= true; } 310 311 /** Note that we have exited from the change buffer code. */ exit_ibufmtr_t312 void exit_ibuf() { m_inside_ibuf= false; } 313 314 /** @return true if we are inside the change buffer code */ is_inside_ibufmtr_t315 bool is_inside_ibuf() const { return m_inside_ibuf; } 316 317 /** Note that pages has been trimed */ set_trim_pagesmtr_t318 void set_trim_pages() { m_trim_pages= true; } 319 320 /** @return true if pages has been trimed */ is_trim_pagesmtr_t321 bool is_trim_pages() { return m_trim_pages; } 322 323 #ifdef UNIV_DEBUG 324 /** Check if we are holding an rw-latch in this mini-transaction 325 @param lock latch to search for 326 @param type held latch type 327 @return whether (lock,type) is contained */ 328 bool memo_contains(const rw_lock_t &lock, mtr_memo_type_t type) 329 MY_ATTRIBUTE((warn_unused_result)); 330 /** Check if we are holding exclusive tablespace latch 331 @param space tablespace to search for 332 @return whether space.latch is being held */ 333 bool memo_contains(const fil_space_t& space) 334 MY_ATTRIBUTE((warn_unused_result)); 335 336 337 /** Check if memo contains the given item. 338 @param object object to search 339 @param flags specify types of object (can be ORred) of 340 MTR_MEMO_PAGE_S_FIX ... values 341 @return true if contains */ 342 bool memo_contains_flagged(const void* ptr, ulint flags) const; 343 344 /** Check if memo contains the given page. 345 @param[in] ptr pointer to within buffer frame 346 @param[in] flags specify types of object with OR of 347 MTR_MEMO_PAGE_S_FIX... values 348 @return the block 349 @retval NULL if not found */ 350 buf_block_t* memo_contains_page_flagged( 351 const byte* ptr, 352 ulint flags) const; 353 354 /** Print info of an mtr handle. */ 355 void print() const; 356 357 /** @return true if mini-transaction contains modifications. */ has_modificationsmtr_t358 bool has_modifications() const { return m_modifications; } 359 360 /** @return the memo stack */ get_memomtr_t361 const mtr_buf_t* get_memo() const { return &m_memo; } 362 363 /** @return the memo stack */ get_memomtr_t364 mtr_buf_t* get_memo() { return &m_memo; } 365 #endif /* UNIV_DEBUG */ 366 367 /** @return true if a record was added to the mini-transaction */ is_dirtymtr_t368 bool is_dirty() const { return m_made_dirty; } 369 370 /** Get the buffered redo log of this mini-transaction. 371 @return redo log */ get_logmtr_t372 const mtr_buf_t* get_log() const { return &m_log; } 373 374 /** Get the buffered redo log of this mini-transaction. 375 @return redo log */ get_logmtr_t376 mtr_buf_t* get_log() { return &m_log; } 377 378 /** Push an object to an mtr memo stack. 379 @param object object 380 @param type object type: MTR_MEMO_S_LOCK, ... */ 381 inline void memo_push(void* object, mtr_memo_type_t type); 382 383 /** Check if this mini-transaction is dirtying a clean page. 384 @param block block being x-fixed 385 @return true if the mtr is dirtying a clean page. */ 386 static inline bool is_block_dirtied(const buf_block_t* block) 387 MY_ATTRIBUTE((warn_unused_result)); 388 389 /** Write request types */ 390 enum write_type 391 { 392 /** the page is guaranteed to always change */ 393 NORMAL= 0, 394 /** optional: the page contents might not change */ 395 MAYBE_NOP, 396 /** force a write, even if the page contents is not changing */ 397 FORCED 398 }; 399 400 /** Write 1, 2, 4, or 8 bytes to a file page. 401 @param[in] block file page 402 @param[in,out] ptr pointer in file page 403 @param[in] val value to write 404 @tparam l number of bytes to write 405 @tparam w write request type 406 @tparam V type of val 407 @return whether any log was written */ 408 template<unsigned l,write_type w= NORMAL,typename V> 409 inline bool write(const buf_block_t &block, void *ptr, V val) 410 MY_ATTRIBUTE((nonnull)); 411 412 /** Log a write of a byte string to a page. 413 @param[in] b buffer page 414 @param[in] ofs byte offset from b->frame 415 @param[in] len length of the data to write */ 416 inline void memcpy(const buf_block_t &b, ulint ofs, ulint len); 417 418 /** Write a byte string to a page. 419 @param[in,out] b buffer page 420 @param[in] dest destination within b.frame 421 @param[in] str the data to write 422 @param[in] len length of the data to write 423 @tparam w write request type */ 424 template<write_type w= NORMAL> 425 inline void memcpy(const buf_block_t &b, void *dest, const void *str, 426 ulint len); 427 428 /** Log a write of a byte string to a ROW_FORMAT=COMPRESSED page. 429 @param[in] b ROW_FORMAT=COMPRESSED index page 430 @param[in] offset byte offset from b.zip.data 431 @param[in] len length of the data to write */ 432 inline void zmemcpy(const buf_block_t &b, ulint offset, ulint len); 433 434 /** Write a byte string to a ROW_FORMAT=COMPRESSED page. 435 @param[in] b ROW_FORMAT=COMPRESSED index page 436 @param[in] dest destination within b.zip.data 437 @param[in] str the data to write 438 @param[in] len length of the data to write 439 @tparam w write request type */ 440 template<write_type w= NORMAL> 441 inline void zmemcpy(const buf_block_t &b, void *dest, const void *str, 442 ulint len); 443 444 /** Log an initialization of a string of bytes. 445 @param[in] b buffer page 446 @param[in] ofs byte offset from b->frame 447 @param[in] len length of the data to write 448 @param[in] val the data byte to write */ 449 inline void memset(const buf_block_t &b, ulint ofs, ulint len, byte val); 450 451 /** Initialize a string of bytes. 452 @param[in,out] b buffer page 453 @param[in] ofs byte offset from b->frame 454 @param[in] len length of the data to write 455 @param[in] val the data byte to write */ 456 inline void memset(const buf_block_t *b, ulint ofs, ulint len, byte val); 457 458 /** Log an initialization of a repeating string of bytes. 459 @param[in] b buffer page 460 @param[in] ofs byte offset from b->frame 461 @param[in] len length of the data to write, in bytes 462 @param[in] str the string to write 463 @param[in] size size of str, in bytes */ 464 inline void memset(const buf_block_t &b, ulint ofs, size_t len, 465 const void *str, size_t size); 466 467 /** Initialize a repeating string of bytes. 468 @param[in,out] b buffer page 469 @param[in] ofs byte offset from b->frame 470 @param[in] len length of the data to write, in bytes 471 @param[in] str the string to write 472 @param[in] size size of str, in bytes */ 473 inline void memset(const buf_block_t *b, ulint ofs, size_t len, 474 const void *str, size_t size); 475 476 /** Log that a string of bytes was copied from the same page. 477 @param[in] b buffer page 478 @param[in] d destination offset within the page 479 @param[in] s source offset within the page 480 @param[in] len length of the data to copy */ 481 inline void memmove(const buf_block_t &b, ulint d, ulint s, ulint len); 482 483 /** Initialize an entire page. 484 @param[in,out] b buffer page */ 485 void init(buf_block_t *b); 486 /** Free a page. 487 @param[in] space tablespace contains page to be freed 488 @param[in] offset page offset to be freed */ 489 inline void free(fil_space_t &space, uint32_t offset); 490 /** Write log for partly initializing a B-tree or R-tree page. 491 @param block B-tree or R-tree page 492 @param comp false=ROW_FORMAT=REDUNDANT, true=COMPACT or DYNAMIC */ 493 inline void page_create(const buf_block_t &block, bool comp); 494 495 /** Write log for inserting a B-tree or R-tree record in 496 ROW_FORMAT=REDUNDANT. 497 @param block B-tree or R-tree page 498 @param reuse false=allocate from PAGE_HEAP_TOP; true=reuse PAGE_FREE 499 @param prev_rec byte offset of the predecessor of the record to insert, 500 starting from PAGE_OLD_INFIMUM 501 @param info_bits info_bits of the record 502 @param n_fields_s number of fields << 1 | rec_get_1byte_offs_flag() 503 @param hdr_c number of common record header bytes with prev_rec 504 @param data_c number of common data bytes with prev_rec 505 @param hdr record header bytes to copy to the log 506 @param hdr_l number of copied record header bytes 507 @param data record payload bytes to copy to the log 508 @param data_l number of copied record data bytes */ 509 inline void page_insert(const buf_block_t &block, bool reuse, 510 ulint prev_rec, byte info_bits, 511 ulint n_fields_s, size_t hdr_c, size_t data_c, 512 const byte *hdr, size_t hdr_l, 513 const byte *data, size_t data_l); 514 /** Write log for inserting a B-tree or R-tree record in 515 ROW_FORMAT=COMPACT or ROW_FORMAT=DYNAMIC. 516 @param block B-tree or R-tree page 517 @param reuse false=allocate from PAGE_HEAP_TOP; true=reuse PAGE_FREE 518 @param prev_rec byte offset of the predecessor of the record to insert, 519 starting from PAGE_NEW_INFIMUM 520 @param info_status rec_get_info_and_status_bits() 521 @param shift unless !reuse: number of bytes the PAGE_FREE is moving 522 @param hdr_c number of common record header bytes with prev_rec 523 @param data_c number of common data bytes with prev_rec 524 @param hdr record header bytes to copy to the log 525 @param hdr_l number of copied record header bytes 526 @param data record payload bytes to copy to the log 527 @param data_l number of copied record data bytes */ 528 inline void page_insert(const buf_block_t &block, bool reuse, 529 ulint prev_rec, byte info_status, 530 ssize_t shift, size_t hdr_c, size_t data_c, 531 const byte *hdr, size_t hdr_l, 532 const byte *data, size_t data_l); 533 /** Write log for deleting a B-tree or R-tree record in ROW_FORMAT=REDUNDANT. 534 @param block B-tree or R-tree page 535 @param prev_rec byte offset of the predecessor of the record to delete, 536 starting from PAGE_OLD_INFIMUM */ 537 inline void page_delete(const buf_block_t &block, ulint prev_rec); 538 /** Write log for deleting a COMPACT or DYNAMIC B-tree or R-tree record. 539 @param block B-tree or R-tree page 540 @param prev_rec byte offset of the predecessor of the record to delete, 541 starting from PAGE_NEW_INFIMUM 542 @param hdr_size record header size, excluding REC_N_NEW_EXTRA_BYTES 543 @param data_size data payload size, in bytes */ 544 inline void page_delete(const buf_block_t &block, ulint prev_rec, 545 size_t hdr_size, size_t data_size); 546 547 /** Write log for initializing an undo log page. 548 @param block undo page */ 549 inline void undo_create(const buf_block_t &block); 550 /** Write log for appending an undo log record. 551 @param block undo page 552 @param data record within the undo page 553 @param len length of the undo record, in bytes */ 554 inline void undo_append(const buf_block_t &block, 555 const void *data, size_t len); 556 /** Trim the end of a tablespace. 557 @param id first page identifier that will not be in the file */ 558 inline void trim_pages(const page_id_t id); 559 560 /** Write a log record about a file operation. 561 @param type file operation 562 @param space_id tablespace identifier 563 @param path file path 564 @param new_path new file path for type=FILE_RENAME */ 565 inline void log_file_op(mfile_type_t type, ulint space_id, 566 const char *path, 567 const char *new_path= nullptr); 568 569 /** Add freed page numbers to freed_pages */ add_freed_offsetmtr_t570 void add_freed_offset(fil_space_t *space, uint32_t page) 571 { 572 ut_ad(is_named_space(space)); 573 if (!m_freed_pages) 574 { 575 m_freed_pages= new range_set(); 576 ut_ad(!m_freed_space); 577 m_freed_space= space; 578 } 579 else 580 ut_ad(m_freed_space == space); 581 m_freed_pages->add_value(page); 582 } 583 584 /** Determine the added buffer fix count of a block. 585 @param block block to be checked 586 @return number of buffer count added by this mtr */ 587 uint32_t get_fix_count(const buf_block_t *block) const; 588 589 /** type of page flushing is needed during commit() */ 590 enum page_flush_ahead 591 { 592 /** no need to trigger page cleaner */ 593 PAGE_FLUSH_NO= 0, 594 /** asynchronous flushing is needed */ 595 PAGE_FLUSH_ASYNC, 596 /** furious flushing is needed */ 597 PAGE_FLUSH_SYNC 598 }; 599 600 private: 601 /** Log a write of a byte string to a page. 602 @param block buffer page 603 @param offset byte offset within page 604 @param data data to be written 605 @param len length of the data, in bytes */ 606 inline void memcpy_low(const buf_block_t &block, uint16_t offset, 607 const void *data, size_t len); 608 /** 609 Write a log record. 610 @tparam type redo log record type 611 @param id persistent page identifier 612 @param bpage buffer pool page, or nullptr 613 @param len number of additional bytes to write 614 @param alloc whether to allocate the additional bytes 615 @param offset byte offset, or 0 if the record type does not allow one 616 @return end of mini-transaction log, minus len */ 617 template<byte type> 618 inline byte *log_write(const page_id_t id, const buf_page_t *bpage, 619 size_t len= 0, bool alloc= false, size_t offset= 0); 620 621 /** Write an EXTENDED log record. 622 @param block buffer pool page 623 @param type extended record subtype; @see mrec_ext_t */ 624 inline void log_write_extended(const buf_block_t &block, byte type); 625 626 /** Append the redo log records to the redo log buffer. 627 @return {start_lsn,flush_ahead} */ 628 std::pair<lsn_t,page_flush_ahead> do_write(); 629 630 /** Append the redo log records to the redo log buffer. 631 @param len number of bytes to write 632 @return {start_lsn,flush_ahead} */ 633 inline std::pair<lsn_t,page_flush_ahead> finish_write(ulint len); 634 635 /** Release the resources */ 636 inline void release_resources(); 637 638 #ifdef UNIV_DEBUG 639 public: 640 /** @return whether the mini-transaction is active */ is_activemtr_t641 bool is_active() const 642 { ut_ad(!m_commit || m_start); return m_start && !m_commit; } 643 /** @return whether the mini-transaction has been committed */ has_committedmtr_t644 bool has_committed() const { ut_ad(!m_commit || m_start); return m_commit; } 645 private: 646 /** whether start() has been called */ 647 bool m_start= false; 648 /** whether commit() has been called */ 649 bool m_commit= false; 650 #endif 651 652 /** The page of the most recent m_log record written, or NULL */ 653 const buf_page_t* m_last; 654 /** The current byte offset in m_last, or 0 */ 655 uint16_t m_last_offset; 656 657 /** specifies which operations should be logged; default MTR_LOG_ALL */ 658 uint16_t m_log_mode:2; 659 660 /** whether at least one buffer pool page was written to */ 661 uint16_t m_modifications:1; 662 663 /** whether at least one previously clean buffer pool page was written to */ 664 uint16_t m_made_dirty:1; 665 666 /** whether change buffer is latched; only needed in non-debug builds 667 to suppress some read-ahead operations, @see ibuf_inside() */ 668 uint16_t m_inside_ibuf:1; 669 670 /** whether the pages has been trimmed */ 671 uint16_t m_trim_pages:1; 672 673 #ifdef UNIV_DEBUG 674 /** Persistent user tablespace associated with the 675 mini-transaction, or 0 (TRX_SYS_SPACE) if none yet */ 676 uint32_t m_user_space_id; 677 #endif /* UNIV_DEBUG */ 678 679 /** acquired dict_index_t::lock, fil_space_t::latch, buf_block_t */ 680 mtr_buf_t m_memo; 681 682 /** mini-transaction log */ 683 mtr_buf_t m_log; 684 685 /** user tablespace that is being modified by the mini-transaction */ 686 fil_space_t* m_user_space; 687 688 /** LSN at commit time */ 689 lsn_t m_commit_lsn; 690 691 /** tablespace where pages have been freed */ 692 fil_space_t *m_freed_space= nullptr; 693 /** set of freed page ids */ 694 range_set *m_freed_pages= nullptr; 695 }; 696 697 #include "mtr0mtr.inl" 698 699 #endif /* mtr0mtr_h */ 700