mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 10:14:19 +01:00
MDEV-27800: Avoid garbage TRX_UNDO_TRX_NO on TRX_UNDO_CACHED pages
In commitc7d0448797
(MDEV-15132) MariaDB Server 10.3 stopped writing the latest transaction identifier to the TRX_SYS page. Instead, the transaction identifier will be recovered from undo log pages. Unfortunately, before commit3926673ce7
and mysql/mysql-server@dc29792ff2 (MySQL 5.1.48 or MariaDB 5.1.48) InnoDB did not always initialize all data fields, but some garbage could be left behind in unused parts of data pages. In undo log pages that are essentially free, but added to a list for reuse (TRX_UNDO_CACHED) the TRX_UNDO_TRX_NO fields could contain garbage, instead of 0. As long as such undo pages are being reused and never marked completely free, the garbage contents may remain forever. In fact, the function trx_undo_header_create() and the record MLOG_UNDO_HDR_CREATE will only initialize TRX_UNDO_TRX_ID, but leave TRX_UNDO_TRX_NO uninitialized. trx_undo_mem_create_at_db_start(): Only read the TRX_UNDO_TRX_NO fields of TRX_UNDO_CACHED pages if the TRX_UNDO_PAGE_TYPE is 0, that is, the page was updated by MariaDB Server 10.3. Earlier versions would always write the TRX_UNDO_PAGE_TYPE as 1 or 2. trx_undo_header_create(): Zero out the TRX_UNDO_TRX_NO field. Strictly speaking, this will change the semantics of the MLOG_UNDO_HDR_CREATE record, but it should not do any harm to overwrite a potentially garbage field with zeroes. Note: This fix will only help future upgrades straight from MariaDB Server 10.2 or MySQL 5.6 or earlier. If such an upgrade has already been made, then an earlier server startup could have fast-forwarded the transaction ID sequence to a large value. If this large value cannot be represented in 48 bits (the size of the DB_TRX_ID column in clustered index records), then various strange things can happen.
This commit is contained in:
parent
535bef86ad
commit
0635088deb
1 changed files with 11 additions and 3 deletions
|
@ -1,7 +1,7 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2014, 2021, MariaDB Corporation.
|
||||
Copyright (c) 2014, 2022, MariaDB Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
|
@ -639,6 +639,7 @@ trx_undo_header_create(
|
|||
mach_write_to_2(log_hdr + TRX_UNDO_NEEDS_PURGE, 1);
|
||||
|
||||
mach_write_to_8(log_hdr + TRX_UNDO_TRX_ID, trx_id);
|
||||
memset(log_hdr + TRX_UNDO_TRX_NO, 0, 8);
|
||||
mach_write_to_2(log_hdr + TRX_UNDO_LOG_START, new_free);
|
||||
|
||||
mach_write_to_1(log_hdr + TRX_UNDO_XID_EXISTS, FALSE);
|
||||
|
@ -1112,12 +1113,19 @@ corrupted:
|
|||
sql_print_error("InnoDB: unsupported undo header state %u",
|
||||
state);
|
||||
goto corrupted;
|
||||
case TRX_UNDO_CACHED:
|
||||
if (UNIV_UNLIKELY(type != 0)) {
|
||||
/* This undo page was not updated by MariaDB
|
||||
10.3 or later. The TRX_UNDO_TRX_NO field may
|
||||
contain garbage. */
|
||||
break;
|
||||
}
|
||||
goto read_trx_no;
|
||||
case TRX_UNDO_TO_PURGE:
|
||||
if (UNIV_UNLIKELY(type == 1)) {
|
||||
goto corrupted_type;
|
||||
}
|
||||
/* fall through */
|
||||
case TRX_UNDO_CACHED:
|
||||
read_trx_no:
|
||||
trx_id_t id = mach_read_from_8(TRX_UNDO_TRX_NO + undo_header);
|
||||
if (id >> 48) {
|
||||
sql_print_error("InnoDB: corrupted TRX_NO %llx", id);
|
||||
|
|
Loading…
Add table
Reference in a new issue