Commit 0635088d authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-27800: Avoid garbage TRX_UNDO_TRX_NO on TRX_UNDO_CACHED pages

In commit c7d04487 (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 commit 3926673c
and mysql/mysql-server@dc29792ff2996aefbb6e64bb2f0bc3aa8fc879e9
(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.
parent 535bef86
/*****************************************************************************
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 @@ trx_undo_mem_create_at_db_start(trx_rseg_t *rseg, ulint id, uint32_t page_no,
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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment