1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605
|
/*****************************************************************************
Copyright (c) 2013, 2025, Oracle and/or its affiliates.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
briefly in the InnoDB documentation. The contributions by Google are
incorporated with their permission, and subject to the conditions contained in
the file COPYING.Google.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License, version 2.0, as published by the
Free Software Foundation.
This program is designed to work with certain software (including
but not limited to OpenSSL) that is licensed under separate terms,
as designated in a particular file or component or in included license
documentation. The authors of MySQL hereby grant you an additional
permission to link the program and your derivative works with the
separately licensed software that they have either included with
the program or referenced in the documentation.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*****************************************************************************/
/**************************************************/ /**
@file include/log0types.h
Redo log basic types
*******************************************************/
#ifndef log0types_h
#define log0types_h
/* std::atomic<X> */
#include <atomic>
/* std::chrono::X */
#include <chrono>
/* std::string */
#include <string>
/* byte */
#include "univ.i"
/* os_offset_t */
#include "os0file.h"
/* ut::INNODB_CACHE_LINE_SIZE */
#include "ut0cpu_cache.h"
/** Type used for all log sequence number storage and arithmetic. */
typedef uint64_t lsn_t;
/** Log file id (0 for ib_redo0) */
typedef size_t Log_file_id;
/** Log flags (stored in file header of log file). */
typedef uint32_t Log_flags;
/** Number which tries to uniquely identify a created set of redo log files.
Redo log files, which have different values of Log_uuid, most likely have been
created for different directories and cannot be mixed. This way foreign redo
files might be easily recognized. When that is the case, most likely something
went wrong when copying files. */
typedef uint32_t Log_uuid;
/** Print format for lsn_t values, used in functions like printf. */
#define LSN_PF UINT64PF
/** Alias for atomic based on lsn_t. */
using atomic_lsn_t = std::atomic<lsn_t>;
/** Type used for sn values, which enumerate bytes of data stored in the log.
Note that these values skip bytes of headers and footers of log blocks. */
typedef uint64_t sn_t;
/** Alias for atomic based on sn_t. */
using atomic_sn_t = std::atomic<sn_t>;
/* The lsn_t, sn_t, Log_file_id are known so constants can be expressed. */
#include "log0constants.h"
/** Enumerates checkpoint headers in the redo log file. */
enum class Log_checkpoint_header_no : uint32_t {
/** The first checkpoint header. */
HEADER_1,
/** The second checkpoint header. */
HEADER_2
};
/** Type used for counters in log_t: flushes_requested and flushes_expected.
They represent number of requests to flush the redo log to disk. */
typedef std::atomic<int64_t> log_flushes_t;
/** Type of redo log file. */
enum class Log_file_type {
/** Usual redo log file, most likely with important redo data. */
NORMAL,
/** Unused redo log file, might always be removed. */
UNUSED
};
/** Callback called on each read or write operation on a redo log file.
@param[in] file_id id of the redo log file (target of the IO operation)
@param[in] file_type type of the redo log file
@param[in] offset offset in the file, at which read or write operation
is going to start (expressed in bytes and computed
from the beginning of the file)
@param[in] size size of data that is going to be read or written in
the IO operation */
typedef std::function<void(Log_file_id file_id, Log_file_type file_type,
os_offset_t offset, os_offset_t size)>
Log_file_io_callback;
/** Function used to calculate checksums of log blocks. */
typedef std::atomic<uint32_t (*)(const byte *log_block)>
Log_checksum_algorithm_atomic_ptr;
/** Clock used to measure time spent in redo log (e.g. when flushing). */
using Log_clock = std::chrono::high_resolution_clock;
/** Time point defined by the Log_clock. */
using Log_clock_point = std::chrono::time_point<Log_clock>;
/** Supported redo log formats. Stored in LOG_HEADER_FORMAT. */
enum class Log_format : uint32_t {
/** Unknown format of redo file. */
LEGACY = 0,
/** The MySQL 5.7.9 redo log format identifier. We can support recovery
from this format if the redo log is clean (logically empty). */
VERSION_5_7_9 = 1,
/** Remove MLOG_FILE_NAME and MLOG_CHECKPOINT, introduce MLOG_FILE_OPEN
redo log record. */
VERSION_8_0_1 = 2,
/** Allow checkpoint_lsn to point any data byte within redo log (before
it had to point the beginning of a group of log records). */
VERSION_8_0_3 = 3,
/** Expand ulint compressed form. */
VERSION_8_0_19 = 4,
/** Row versioning header. */
VERSION_8_0_28 = 5,
/** Introduced with innodb_redo_log_capacity:
- write LSN does not re-enter file with checkpoint_lsn,
- epoch_no is checked strictly during recovery. */
VERSION_8_0_30 = 6,
/** The redo log format identifier
corresponding to the current format version. */
CURRENT = VERSION_8_0_30
};
/** Ruleset defining how redo log files are named, where they are stored,
when they are created and what sizes could they have. */
enum class Log_files_ruleset {
/** Redo log files were named ib_logfile0, ib_logfile1, ... ib_logfile99.
Redo log files were pre-created during startup and re-used after wrapping.
Redo log files had the same file size and supported formats < VERSION_8_0_30.
The non-initialized set of redo log files was denoted by existence of the
ib_logfile101. The log files were located directly in the root directory
(innodb_log_group_home_dir if specified; else: datadir). */
PRE_8_0_30,
/** Redo log files are named #ib_redo0, #ib_redo1, ... and no longer wrapped.
Redo log files are created on-demand during runtime and might have different
sizes. Formats >= VERSION_8_0_30 are supported. The redo log files are located
in #innodb_redo subdirectory in the root directory - for example:
- if innodb_log_group_home_dir = '/srv/my_db/logs', then redo files are in
'/srv/my_db/logs/#innodb_redo/',
- if innodb_log_group_home_dir is not specified and datadir='/srv/my_db',
then redo files are in '/srv/my_db/#innodb_redo'. */
CURRENT
};
/** Direction of resize operation. */
enum class Log_resize_mode {
/** No pending resize. */
NONE,
/** Resizing down. */
RESIZING_DOWN
};
/** Configures path to the root directory, where redo subdirectory might be
located (or redo log files if the ruleset is older). Configures the ruleset
that should be used when locating redo log files. */
struct Log_files_context {
explicit Log_files_context(
const std::string &root_path = "",
Log_files_ruleset files_ruleset = Log_files_ruleset::CURRENT);
/** Path to the root directory. */
std::string m_root_path;
/** Ruleset determining how file paths are built. */
Log_files_ruleset m_files_ruleset;
};
/** Meta data stored in log file header. */
struct Log_file_header {
/** Format of the log file. */
uint32_t m_format;
/** LSN of the first log block (%512 == 0). */
lsn_t m_start_lsn;
/** Creator name. */
std::string m_creator_name;
/** Log flags. Meaning of bit positions is to be found in documentation
of LOG_HEADER_FLAG_* constants in log0constants.h. */
Log_flags m_log_flags;
/** UUID value describing the whole group of log files. */
Log_uuid m_log_uuid;
};
/** Meta data stored in one of two checkpoint headers. */
struct Log_checkpoint_header {
/** Checkpoint LSN (oldest_lsn_lwm from the moment of checkpoint). */
lsn_t m_checkpoint_lsn;
};
/** Meta data stored in header of a log data block. */
struct Log_data_block_header {
/** Together with m_hdr_no form unique identifier of this block,
@see LOG_BLOCK_EPOCH_NO. */
uint32_t m_epoch_no;
/** Together with m_epoch_no form unique identifier of this block,
@see log_block_get_hdr_no. Each next log data block has hdr_no
incremented by 1 (unless wrapped). */
uint32_t m_hdr_no;
/** Offset up to which this block has data inside, computed from the
beginning of the block. */
uint16_t m_data_len;
/** Offset to the first mtr starting in this block, or 0 if there is no
mtr starting in this block. */
uint16_t m_first_rec_group;
/** Sets m_epoch_no and m_hdr_no from a single lsn
*/
void set_lsn(lsn_t lsn);
};
/** Pair of: log file id and log file size (expressed in bytes). */
struct Log_file_id_and_size {
Log_file_id_and_size() = default;
Log_file_id_and_size(Log_file_id id, os_offset_t size)
: m_id(id), m_size_in_bytes(size) {}
/** Id of the file. */
Log_file_id m_id{};
/** Size of file, expressed in bytes. */
os_offset_t m_size_in_bytes{};
};
/** Pair of: log file id and log file header. */
struct Log_file_id_and_header {
Log_file_id_and_header() = default;
Log_file_id_and_header(Log_file_id id, Log_file_header header)
: m_id(id), m_header(header) {}
/** Id of the file. */
Log_file_id m_id{};
/** Main header of the file. */
Log_file_header m_header{};
};
/** Type of access allowed for the opened redo log file. */
enum class Log_file_access_mode {
/** The opened file can be both read and written. */
READ_WRITE,
/** The opened file can be only read. */
READ_ONLY,
/** The opened file can be only written. */
WRITE_ONLY,
};
/** Handle which allows to do reads / writes for the opened file.
For particular kind of reads or writes (for checkpoint headers,
data blocks, main file header or encryption header) there are helper
functions defined outside this class. Unless you wanted to transfer
the whole file as-is, you should rather use those functions for
read/write operations. */
class Log_file_handle {
public:
explicit Log_file_handle(Encryption_metadata &encryption_metadata);
Log_file_handle(Log_file_handle &&other);
Log_file_handle &operator=(Log_file_handle &&rhs);
/** Closes handle if was opened (calling fsync if was modified).
Destructs the handle object. */
~Log_file_handle();
/** @return true iff file is opened (by this handle) */
bool is_open() const;
/** Closes file represented by this handle (must be opened). */
void close();
/** @return id of the log file */
Log_file_id file_id() const;
/** @return path to the log file (including the file name) */
const std::string &file_path() const;
/** @return file size in bytes */
os_offset_t file_size() const;
/** Reads from the log file at the given offset (to the provided buffer).
@param[in] read_offset offset in bytes from the beginning of the file
@param[in] read_size number of bytes to read
@param[out] buf allocated buffer to fill when reading
@return DB_SUCCESS or error */
dberr_t read(os_offset_t read_offset, os_offset_t read_size, byte *buf);
/** Writes the provided buffer to the log file at the given offset.
@param[in] write_offset offset in bytes from the beginning of the file
@param[in] write_size number of bytes to write
@param[in] buf buffer to write
@return DB_SUCCESS or error */
dberr_t write(os_offset_t write_offset, os_offset_t write_size,
const byte *buf);
/** Executes fsync operation for this redo log file. */
void fsync();
/** @return number of fsyncs in-progress */
static uint64_t fsyncs_in_progress() { return s_fsyncs_in_progress.load(); }
/** @return total number of fsyncs that have been started since
the server has started */
static uint64_t total_fsyncs() { return s_total_fsyncs.load(); }
/** Callback called on each read operation. */
static Log_file_io_callback s_on_before_read;
/** Callback called on each write operation. */
static Log_file_io_callback s_on_before_write;
/** True iff all fsyncs should be no-op. */
static bool s_skip_fsyncs;
private:
friend struct Log_file;
/** Tries to open a given redo log file with with a given access mode.
If succeeded then this handle represents the opened file and allows to
performs reads and/or writes (depends on the requested access mode).
If encountered error during the attempt to open, error message is emitted
to the error log, in which case this handle remains closed.
@param[in] files_ctx context within which files exist
@param[in] id id of the log file
@param[in] access_mode access mode for the opened file
@param[in] encryption_metadata encryption metadata
@param[in] file_type type of redo file */
Log_file_handle(const Log_files_context &files_ctx, Log_file_id id,
Log_file_access_mode access_mode,
Encryption_metadata &encryption_metadata,
Log_file_type file_type);
Log_file_handle(const Log_file_handle &other) = delete;
Log_file_handle &operator=(const Log_file_handle &rhs) = delete;
/** Open the log file with the configured access mode.
@return DB_SUCCESS or error */
dberr_t open();
/** Creates and configures an io request object according to currently
configured encryption metadata (m_encryption_*) and m_block_size.
@param[in] req_type defines type of IO operation (read or write)
@param[in] offset offset in bytes from the beginning of the file
@param[in] size number of bytes to write or read
@param[in] can_use_encryption e.g. whether newly blocks should be encrypted
@return IORequest instance */
IORequest prepare_io_request(int req_type, os_offset_t offset,
os_offset_t size, bool can_use_encryption);
#ifdef UNIV_DEBUG
/** Number of all opened Log_file_handle existing currently. */
static std::atomic<size_t> s_n_open;
#endif /* UNIV_DEBUG */
/** Number of fsyncs in-progress. */
static std::atomic<uint64_t> s_fsyncs_in_progress;
/** Total number of fsyncs that have been started since
the server has started. */
static std::atomic<uint64_t> s_total_fsyncs;
/** Id of the redo log file (part of its file name) */
Log_file_id m_file_id;
/** Access mode allowed for this handle (if not yet closed). */
Log_file_access_mode m_access_mode;
/** Encryption metadata to be used for all IO operations on this file
except those related to the first LOG_FILE_HDR_SIZE bytes.
@remarks If Encryption::set_key() and Encryption::set_initial_vector()
started to accept their arguments as const pointers, this could become
a const pointer too). In such case, all usages of Encryption_metadata*
inside redo log code, could also become changed to usages of the const
pointer. */
Encryption_metadata &m_encryption_metadata;
/** Type of redo log file. */
Log_file_type m_file_type;
/** Whether file is opened */
bool m_is_open;
/** Whether file has been modified using this handle since it was opened. */
bool m_is_modified;
/** File name */
std::string m_file_path;
/** OS handle for file (if opened) */
pfs_os_file_t m_raw_handle;
/** Size of single physical block (if opened) */
os_offset_t m_block_size;
/** Size of file in bytes (if opened) */
os_offset_t m_file_size;
};
/** Meta information about single log file. */
struct Log_file {
Log_file(const Log_files_context &files_ctx,
Encryption_metadata &encryption_metadata);
Log_file(const Log_files_context &files_ctx, Log_file_id id, bool consumed,
bool full, os_offset_t size_in_bytes, lsn_t start_lsn, lsn_t end_lsn,
Encryption_metadata &encryption_metadata);
Log_file(const Log_file &other) = default;
Log_file &operator=(const Log_file &other);
/** Context within which this file exists. */
const Log_files_context &m_files_ctx;
/** ID of the file. */
Log_file_id m_id;
/** Set to true when file becomes consumed. */
bool m_consumed;
/** Set to true when file became full and next file exists. */
bool m_full;
/** Size, expressed in bytes, including LOG_FILE_HDR_SIZE. */
os_offset_t m_size_in_bytes;
/** LSN of the first byte within the file, aligned to
OS_FILE_LOG_BLOCK_SIZE. */
lsn_t m_start_lsn;
/** LSN of the first byte after the file, aligned to
OS_FILE_LOG_BLOCK_SIZE. */
lsn_t m_end_lsn;
/** Encryption metadata passed to opened file handles
@see Log_file_handle::m_encryption_metadata */
Encryption_metadata &m_encryption_metadata;
/** Checks if this object is equal to a given another object.
@param[in] rhs the object to compare against
@return true iff all related fields of the two objects are equal */
bool operator==(const Log_file &rhs) const {
return m_id == rhs.m_id && m_consumed == rhs.m_consumed &&
m_full == rhs.m_full && m_size_in_bytes == rhs.m_size_in_bytes &&
m_start_lsn == rhs.m_start_lsn && m_end_lsn == rhs.m_end_lsn;
}
/** Validates that lsn fields seem correct (m_start_lsn, m_end_lsn) */
void lsn_validate() const {
ut_a(m_start_lsn == 0 || LOG_START_LSN <= m_start_lsn);
ut_a(m_start_lsn < m_end_lsn);
ut_a(m_start_lsn % OS_FILE_LOG_BLOCK_SIZE == 0);
ut_a(m_end_lsn % OS_FILE_LOG_BLOCK_SIZE == 0);
}
/** Checks if a given lsn belongs to [m_start_lsn, m_end_lsn).
In other words, checks that the given lsn belongs to this file.
@param[in] lsn lsn to test against lsn range
@return true iff lsn is in the file */
bool contains(lsn_t lsn) const {
return m_start_lsn <= lsn && lsn < m_end_lsn;
}
/** Provides offset for the given LSN (from the beginning of the log file).
@param[in] lsn lsn to locate (must exist in the file)
@return offset from the beginning of the file for the given lsn */
os_offset_t offset(lsn_t lsn) const {
lsn_validate();
ut_a(contains(lsn) || lsn == m_end_lsn);
return offset(lsn, m_start_lsn);
}
/** Provides offset for the given LSN and log file with the given start_lsn
(offset from the beginning of the log file).
@param[in] lsn lsn to locate (must be >= file_start_lsn)
@param[in] file_start_lsn start lsn of the log file
@return offset from the beginning of the file for the given lsn */
static os_offset_t offset(lsn_t lsn, lsn_t file_start_lsn) {
return LOG_FILE_HDR_SIZE + (lsn - file_start_lsn);
}
/** Computes id of the next log file. Does not check if such file exists.
@return id of the next log file */
Log_file_id next_id() const { return next_id(m_id, 1); }
/** Opens this file and provides handle that allows to read from this file
and / or write to this file (depends on the requested access mode).
@param[in] access_mode requested access mode (reads and/or writes)
@return handle to the opened file or empty handle with error information */
Log_file_handle open(Log_file_access_mode access_mode) const;
/** Opens a given redo log file and provides handle that allows to read from
that file and / or write to that file (depends on the requested access mode).
@param[in] files_ctx context within which file exists
@param[in] file_id id of the redo log file to open
@param[in] access_mode requested access mode (reads and/or writes)
@param[in] encryption_metadata encryption metadata
@param[in] file_type type of underlying file on disk to open
@return handle to the opened file or empty handle with error information */
static Log_file_handle open(const Log_files_context &files_ctx,
Log_file_id file_id,
Log_file_access_mode access_mode,
Encryption_metadata &encryption_metadata,
Log_file_type file_type = Log_file_type::NORMAL);
/** Computes id + inc, asserting it does not overflow the maximum value.
@param[in] id base id of file, to which inc is added
@param[in] inc number of log files ahead (1 = directly next one)
@return id + inc */
static Log_file_id next_id(Log_file_id id, size_t inc = 1) {
constexpr Log_file_id MAX_FILE_ID = std::numeric_limits<Log_file_id>::max();
ut_a(0 < inc);
ut_a(inc <= MAX_FILE_ID);
ut_a(id <= MAX_FILE_ID - inc);
return id + inc;
}
};
struct alignas(ut::INNODB_CACHE_LINE_SIZE) log_t;
/** Runtime statistics related to redo log files management. These stats are
not persisted to disk. */
struct Log_files_stats {
/** Last time stats were updated (last successful call to @see update()). */
Log_clock_point m_last_update_time{};
/** LSN difference by which result of log_files_oldest_needed_lsn() advanced
during last second. This is basically average consumption speed.
Updated by successful calls to @see update(). */
lsn_t m_lsn_consumption_per_1s{0};
/** LSN difference by which result of log_files_newest_needed_lsn() advanced
during last second. This is basically average production speed.
Updated by successful calls to @see update(). */
lsn_t m_lsn_production_per_1s{0};
/** Oldest LSN returned by log_files_oldest_needed_lsn() during last
successful call to @see update(). */
lsn_t m_oldest_lsn_on_update{0};
/** Newest LSN returned by log_files_newest_needed_lsn() during last
successful call to @see update(). */
lsn_t m_newest_lsn_on_update{0};
/** Tries to update stats. Fails and skips updating if less than 1s elapsed
since last successful update, else: updates the stats and succeeds.
@param[in] log redo log */
void update(const log_t &log);
};
#endif /* !log0types_h */
|