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/log0recv.h 29 Recovery 30 31 Created 9/20/1997 Heikki Tuuri 32 *******************************************************/ 33 34 #ifndef log0recv_h 35 #define log0recv_h 36 37 #include "univ.i" 38 #include "ut0byte.h" 39 #include "buf0types.h" 40 #include "hash0hash.h" 41 #include "log0types.h" 42 #include "log0log.h" 43 #include "mtr0types.h" 44 #include "ut0new.h" 45 46 #include <list> 47 #include <vector> 48 49 /** Check the 4-byte checksum to the trailer checksum field of a log 50 block. 51 @param[in] log block 52 @return whether the checksum matches */ 53 bool 54 log_block_checksum_is_ok( 55 const byte* block) /*!< in: pointer to a log block */ 56 MY_ATTRIBUTE((warn_unused_result)); 57 58 /*******************************************************//** 59 Calculates the new value for lsn when more data is added to the log. */ 60 61 lsn_t 62 recv_calc_lsn_on_data_add( 63 /*======================*/ 64 lsn_t lsn, /*!< in: old lsn */ 65 ib_uint64_t len); /*!< in: this many bytes of data is 66 added, log block headers not included */ 67 68 #ifdef UNIV_HOTBACKUP 69 extern bool recv_replay_file_ops; 70 71 /*******************************************************************//** 72 Reads the checkpoint info needed in hot backup. 73 @return TRUE if success */ 74 ibool 75 recv_read_checkpoint_info_for_backup( 76 /*=================================*/ 77 const byte* hdr, /*!< in: buffer containing the log group 78 header */ 79 lsn_t* lsn, /*!< out: checkpoint lsn */ 80 lsn_t* offset, /*!< out: checkpoint offset in the log group */ 81 lsn_t* cp_no, /*!< out: checkpoint number */ 82 lsn_t* first_header_lsn) 83 /*!< out: lsn of of the start of the 84 first log file */ 85 MY_ATTRIBUTE((nonnull)); 86 /*******************************************************************//** 87 Scans the log segment and n_bytes_scanned is set to the length of valid 88 log scanned. */ 89 void 90 recv_scan_log_seg_for_backup( 91 /*=========================*/ 92 byte* buf, /*!< in: buffer containing log data */ 93 ulint buf_len, /*!< in: data length in that buffer */ 94 lsn_t* scanned_lsn, /*!< in/out: lsn of buffer start, 95 we return scanned lsn */ 96 ulint* scanned_checkpoint_no, 97 /*!< in/out: 4 lowest bytes of the 98 highest scanned checkpoint number so 99 far */ 100 ulint* n_bytes_scanned);/*!< out: how much we were able to 101 scan, smaller than buf_len if log 102 data ended here */ 103 #endif /* UNIV_HOTBACKUP */ 104 /*******************************************************************//** 105 Returns TRUE if recovery is currently running. 106 @return recv_recovery_on */ 107 UNIV_INLINE 108 bool 109 recv_recovery_is_on(void); 110 /*=====================*/ 111 /************************************************************************//** 112 Applies the hashed log records to the page, if the page lsn is less than the 113 lsn of a log record. This can be called when a buffer page has just been 114 read in, or also for a page already in the buffer pool. */ 115 void 116 recv_recover_page_func( 117 /*===================*/ 118 #ifndef UNIV_HOTBACKUP 119 ibool just_read_in, 120 /*!< in: TRUE if the i/o handler calls 121 this for a freshly read page */ 122 #endif /* !UNIV_HOTBACKUP */ 123 buf_block_t* block); /*!< in/out: buffer block */ 124 #ifndef UNIV_HOTBACKUP 125 /** Wrapper for recv_recover_page_func(). 126 Applies the hashed log records to the page, if the page lsn is less than the 127 lsn of a log record. This can be called when a buffer page has just been 128 read in, or also for a page already in the buffer pool. 129 @param jri in: TRUE if just read in (the i/o handler calls this for 130 a freshly read page) 131 @param block in/out: the buffer block 132 */ 133 # define recv_recover_page(jri, block) recv_recover_page_func(jri, block) 134 #else /* !UNIV_HOTBACKUP */ 135 /** Wrapper for recv_recover_page_func(). 136 Applies the hashed log records to the page, if the page lsn is less than the 137 lsn of a log record. This can be called when a buffer page has just been 138 read in, or also for a page already in the buffer pool. 139 @param jri in: TRUE if just read in (the i/o handler calls this for 140 a freshly read page) 141 @param block in/out: the buffer block 142 */ 143 # define recv_recover_page(jri, block) recv_recover_page_func(block) 144 #endif /* !UNIV_HOTBACKUP */ 145 /** Start recovering from a redo log checkpoint. 146 @see recv_recovery_from_checkpoint_finish 147 @param[in] flush_lsn FIL_PAGE_FILE_FLUSH_LSN 148 of first system tablespace page 149 @return error code or DB_SUCCESS */ 150 dberr_t 151 recv_recovery_from_checkpoint_start( 152 lsn_t flush_lsn); 153 /** Complete recovery from a checkpoint. */ 154 void 155 recv_recovery_from_checkpoint_finish(void); 156 /********************************************************//** 157 Initiates the rollback of active transactions. */ 158 void 159 recv_recovery_rollback_active(void); 160 /*===============================*/ 161 162 /** Tries to parse a single log record. 163 @param[out] type log record type 164 @param[in] ptr pointer to a buffer 165 @param[in] end_ptr end of the buffer 166 @param[out] space_id tablespace identifier 167 @param[out] page_no page number 168 @param[in] apply whether to apply MLOG_FILE_* records 169 @param[out] body start of log record body 170 @return length of the record, or 0 if the record was not complete */ 171 172 ulint 173 recv_parse_log_rec( 174 mlog_id_t* type, 175 byte* ptr, 176 byte* end_ptr, 177 ulint* space, 178 ulint* page_no, 179 bool apply, 180 byte** body); 181 182 /******************************************************//** 183 Resets the logs. The contents of log files will be lost! */ 184 void 185 recv_reset_logs( 186 /*============*/ 187 lsn_t lsn); /*!< in: reset to this lsn 188 rounded up to be divisible by 189 OS_FILE_LOG_BLOCK_SIZE, after 190 which we add 191 LOG_BLOCK_HDR_SIZE */ 192 #ifdef UNIV_HOTBACKUP 193 /******************************************************//** 194 Creates new log files after a backup has been restored. */ 195 void 196 recv_reset_log_files_for_backup( 197 /*============================*/ 198 const char* log_dir, /*!< in: log file directory path */ 199 ulint n_log_files, /*!< in: number of log files */ 200 lsn_t log_file_size, /*!< in: log file size */ 201 lsn_t lsn); /*!< in: new start lsn, must be 202 divisible by OS_FILE_LOG_BLOCK_SIZE */ 203 #endif /* UNIV_HOTBACKUP */ 204 /********************************************************//** 205 Creates the recovery system. */ 206 void 207 recv_sys_create(void); 208 /*=================*/ 209 /**********************************************************//** 210 Release recovery system mutexes. */ 211 void 212 recv_sys_close(void); 213 /*================*/ 214 /********************************************************//** 215 Frees the recovery system memory. */ 216 void 217 recv_sys_mem_free(void); 218 /*===================*/ 219 /********************************************************//** 220 Inits the recovery system for a recovery operation. */ 221 void 222 recv_sys_init( 223 /*==========*/ 224 ulint available_memory); /*!< in: available memory in bytes */ 225 #ifndef UNIV_HOTBACKUP 226 /********************************************************//** 227 Frees the recovery system. */ 228 void 229 recv_sys_debug_free(void); 230 /*=====================*/ 231 /********************************************************//** 232 Reset the state of the recovery system variables. */ 233 void 234 recv_sys_var_init(void); 235 /*===================*/ 236 #endif /* !UNIV_HOTBACKUP */ 237 /*******************************************************************//** 238 Empties the hash table of stored log records, applying them to appropriate 239 pages. */ 240 void 241 recv_apply_hashed_log_recs( 242 /*=======================*/ 243 ibool allow_ibuf); /*!< in: if TRUE, also ibuf operations are 244 allowed during the application; if FALSE, 245 no ibuf operations are allowed, and after 246 the application all file pages are flushed to 247 disk and invalidated in buffer pool: this 248 alternative means that no new log records 249 can be generated during the application */ 250 251 /*********************************************************************//** 252 Gets the hashed file address struct for a page. 253 @return file address struct, NULL if not found from the hash table */ 254 255 recv_addr_t* 256 recv_get_fil_addr_struct( 257 /*=====================*/ 258 ulint space, /*!< in: space id */ 259 ulint page_no)/*!< in: page number */ 260 MY_ATTRIBUTE((warn_unused_result)); 261 262 #ifdef UNIV_HOTBACKUP 263 /*******************************************************************//** 264 Applies log records in the hash table to a backup. */ 265 void 266 recv_apply_log_recs_for_backup(void); 267 /*================================*/ 268 #endif /* UNIV_HOTBACKUP */ 269 270 /** Block of log record data */ 271 struct recv_data_t{ 272 recv_data_t* next; /*!< pointer to the next block or NULL */ 273 /*!< the log record data is stored physically 274 immediately after this struct, max amount 275 RECV_DATA_BLOCK_SIZE bytes of it */ 276 }; 277 278 /** Stored log record struct */ 279 struct recv_t{ 280 mlog_id_t type; /*!< log record type */ 281 ulint len; /*!< log record body length in bytes */ 282 recv_data_t* data; /*!< chain of blocks containing the log record 283 body */ 284 lsn_t start_lsn;/*!< start lsn of the log segment written by 285 the mtr which generated this log record: NOTE 286 that this is not necessarily the start lsn of 287 this log record */ 288 lsn_t end_lsn;/*!< end lsn of the log segment written by 289 the mtr which generated this log record: NOTE 290 that this is not necessarily the end lsn of 291 this log record */ 292 UT_LIST_NODE_T(recv_t) 293 rec_list;/*!< list of log records for this page */ 294 }; 295 296 /** States of recv_addr_t */ 297 enum recv_addr_state { 298 /** not yet processed */ 299 RECV_NOT_PROCESSED, 300 /** page is being read */ 301 RECV_BEING_READ, 302 /** log records are being applied on the page */ 303 RECV_BEING_PROCESSED, 304 /** log records have been applied on the page */ 305 RECV_PROCESSED, 306 /** log records have been discarded because the tablespace 307 does not exist */ 308 RECV_DISCARDED 309 }; 310 311 /** Hashed page file address struct */ 312 struct recv_addr_t{ 313 enum recv_addr_state state; 314 /*!< recovery state of the page */ 315 unsigned space:32;/*!< space id */ 316 unsigned page_no:32;/*!< page number */ 317 UT_LIST_BASE_NODE_T(recv_t) 318 rec_list;/*!< list of log records for this page */ 319 hash_node_t addr_hash;/*!< hash node in the hash bucket chain */ 320 }; 321 322 struct recv_dblwr_t { 323 /** Add a page frame to the doublewrite recovery buffer. */ addrecv_dblwr_t324 void add(byte* page) { 325 pages.push_back(page); 326 } 327 328 /** Add a page frame to sys_list and the global list of double 329 write pages. The separate list is used to decrypt doublewrite 330 buffer pages of encrypted system tablespace 331 @param[in] page doublwrite buffer page */ add_to_sysrecv_dblwr_t332 void add_to_sys(byte* page) { 333 sys_pages.push_back(page); 334 pages.push_back(page); 335 } 336 337 /** Find a doublewrite copy of a page. 338 @param[in] space_id tablespace identifier 339 @param[in] page_no page number 340 @return page frame 341 @retval NULL if no page was found */ 342 const byte* find_page(ulint space_id, ulint page_no); 343 344 typedef std::list<byte*, ut_allocator<byte*> > list; 345 346 /** Recovered doublewrite buffer page frames */ 347 list pages; 348 349 /** Pages from system tablespace doublewrite buffer. 350 If encrypted, these pages should be decrypted with system tablespace 351 encryption key. Other pages from parallel double write buffer should 352 be decrypted with their respective tablespace encryption key */ 353 list sys_pages; 354 355 /** Decrypt double write buffer pages if system tablespace is 356 encrypted. This function process only pages from sys_pages list. 357 Other pages from parallel doublewrite buffer will be decrypted after 358 tablespace objects are loaded. */ 359 void decrypt_sys_dblwr_pages(); 360 }; 361 362 /* Recovery encryption information */ 363 typedef struct recv_encryption { 364 ulint space_id; /*!< the page number */ 365 byte* key; /*!< encryption key */ 366 byte* iv; /*!< encryption iv */ 367 } recv_encryption_t; 368 369 typedef std::vector<recv_encryption_t, ut_allocator<recv_encryption_t> > 370 encryption_list_t; 371 372 /** Recovery system data structure */ 373 struct recv_sys_t{ 374 #ifndef UNIV_HOTBACKUP 375 ib_mutex_t mutex; /*!< mutex protecting the fields apply_log_recs, 376 n_addrs, and the state field in each recv_addr 377 struct */ 378 os_event_t flush_start;/*!< event to acticate 379 page cleaner threads */ 380 os_event_t flush_end;/*!< event to signal that the page 381 cleaner has finished the request */ 382 #endif /* !UNIV_HOTBACKUP */ 383 ibool apply_log_recs; 384 /*!< this is TRUE when log rec application to 385 pages is allowed; this flag tells the 386 i/o-handler if it should do log record 387 application */ 388 ibool apply_batch_on; 389 /*!< this is TRUE when a log rec application 390 batch is running */ 391 byte* last_block; 392 /*!< possible incomplete last recovered log 393 block */ 394 byte* last_block_buf_start; 395 /*!< the nonaligned start address of the 396 preceding buffer */ 397 byte* buf; /*!< buffer for parsing log records */ 398 ulint len; /*!< amount of data in buf */ 399 lsn_t parse_start_lsn; 400 /*!< this is the lsn from which we were able to 401 start parsing log records and adding them to 402 the hash table; zero if a suitable 403 start point not found yet */ 404 lsn_t scanned_lsn; 405 /*!< the log data has been scanned up to this 406 lsn */ 407 ulint scanned_checkpoint_no; 408 /*!< the log data has been scanned up to this 409 checkpoint number (lowest 4 bytes) */ 410 ulint recovered_offset; 411 /*!< start offset of non-parsed log records in 412 buf */ 413 lsn_t recovered_lsn; 414 /*!< the log records have been parsed up to 415 this lsn */ 416 bool found_corrupt_log; 417 /*!< set when finding a corrupt log 418 block or record, or there is a log 419 parsing buffer overflow */ 420 bool found_corrupt_fs; 421 /*!< set when an inconsistency with 422 the file system contents is detected 423 during log scan or apply */ 424 lsn_t mlog_checkpoint_lsn; 425 /*!< the LSN of a MLOG_CHECKPOINT 426 record, or 0 if none was parsed */ 427 mem_heap_t* heap; /*!< memory heap of log records and file 428 addresses*/ 429 hash_table_t* addr_hash;/*!< hash table of file addresses of pages */ 430 ulint n_addrs;/*!< number of not processed hashed file 431 addresses in the hash table */ 432 433 recv_dblwr_t dblwr; 434 435 encryption_list_t* /*!< Encryption information list */ 436 encryption_list; 437 set_corrupt_logrecv_sys_t438 void set_corrupt_log() { 439 found_corrupt_log = true; 440 } 441 }; 442 443 /** The recovery system */ 444 extern recv_sys_t* recv_sys; 445 446 /** TRUE when applying redo log records during crash recovery; FALSE 447 otherwise. Note that this is FALSE while a background thread is 448 rolling back incomplete transactions. */ 449 extern volatile bool recv_recovery_on; 450 /** If the following is TRUE, the buffer pool file pages must be invalidated 451 after recovery and no ibuf operations are allowed; this becomes TRUE if 452 the log record hash table becomes too full, and log records must be merged 453 to file pages already before the recovery is finished: in this case no 454 ibuf operations are allowed, as they could modify the pages read in the 455 buffer pool before the pages have been recovered to the up-to-date state. 456 457 TRUE means that recovery is running and no operations on the log files 458 are allowed yet: the variable name is misleading. */ 459 extern bool recv_no_ibuf_operations; 460 /** TRUE when recv_init_crash_recovery() has been called. */ 461 extern bool recv_needed_recovery; 462 #ifdef UNIV_DEBUG 463 /** TRUE if writing to the redo log (mtr_commit) is forbidden. 464 Protected by log_sys->mutex. */ 465 extern bool recv_no_log_write; 466 #endif /* UNIV_DEBUG */ 467 468 /** TRUE if buf_page_is_corrupted() should check if the log sequence 469 number (FIL_PAGE_LSN) is in the future. Initially FALSE, and set by 470 recv_recovery_from_checkpoint_start(). */ 471 extern bool recv_lsn_checks_on; 472 #ifdef UNIV_HOTBACKUP 473 /** TRUE when the redo log is being backed up */ 474 extern bool recv_is_making_a_backup; 475 #endif /* UNIV_HOTBACKUP */ 476 477 /** Size of the parsing buffer; it must accommodate RECV_SCAN_SIZE many 478 times! */ 479 #define RECV_PARSING_BUF_SIZE (2 * 1024 * 1024) 480 481 /** Size of block reads when the log groups are scanned forward to do a 482 roll-forward */ 483 #define RECV_SCAN_SIZE (4 * UNIV_PAGE_SIZE) 484 485 /** This many frames must be left free in the buffer pool when we scan 486 the log and store the scanned log records in the buffer pool: we will 487 use these free frames to read in pages when we start applying the 488 log records to the database. */ 489 extern ulint recv_n_pool_free_frames; 490 491 #ifndef UNIV_NONINL 492 #include "log0recv.ic" 493 #endif 494 495 #endif 496