Commit a0e4853e authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-28668 Recovery or backup of INSERT may be incorrect

page_cur_insert_rec_low(): When checking for common bytes with
the preceding record, exclude the header bytes of next_rec
that could have been updated by this function.

The scenario where this caused corruption was an insert of
a node pointer record. The child page number was written as
0x203 but recovered as 0x103 because the n_owned field of next_rec
was changed from 1 to 2 before the comparison was invoked.
parent 915afddb
/***************************************************************************** /*****************************************************************************
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2018, 2021, MariaDB Corporation. Copyright (c) 2018, 2022, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under 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 the terms of the GNU General Public License as published by the Free Software
...@@ -154,9 +154,8 @@ page_cur_tuple_insert( ...@@ -154,9 +154,8 @@ page_cur_tuple_insert(
MY_ATTRIBUTE((nonnull, warn_unused_result)); MY_ATTRIBUTE((nonnull, warn_unused_result));
/***********************************************************//** /***********************************************************//**
Inserts a record next to page cursor on an uncompressed page. Inserts a record next to page cursor on an uncompressed page.
Returns pointer to inserted record if succeed, i.e., enough @return pointer to record
space available, NULL otherwise. The cursor stays at the same position. @retval nullptr if not enough space was available */
@return pointer to record if succeed, NULL otherwise */
rec_t* rec_t*
page_cur_insert_rec_low( page_cur_insert_rec_low(
/*====================*/ /*====================*/
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc. Copyright (c) 2012, Facebook Inc.
Copyright (c) 2018, 2021, MariaDB Corporation. Copyright (c) 2018, 2022, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under 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 the terms of the GNU General Public License as published by the Free Software
...@@ -1280,9 +1280,8 @@ inline void mtr_t::page_insert(const buf_block_t &block, bool reuse, ...@@ -1280,9 +1280,8 @@ inline void mtr_t::page_insert(const buf_block_t &block, bool reuse,
/***********************************************************//** /***********************************************************//**
Inserts a record next to page cursor on an uncompressed page. Inserts a record next to page cursor on an uncompressed page.
Returns pointer to inserted record if succeed, i.e., enough @return pointer to record
space available, NULL otherwise. The cursor stays at the same position. @retval nullptr if not enough space was available */
@return pointer to record if succeed, NULL otherwise */
rec_t* rec_t*
page_cur_insert_rec_low( page_cur_insert_rec_low(
/*====================*/ /*====================*/
...@@ -1575,8 +1574,12 @@ page_cur_insert_rec_low( ...@@ -1575,8 +1574,12 @@ page_cur_insert_rec_low(
const byte *r= rec; const byte *r= rec;
const byte *c= cur->rec; const byte *c= cur->rec;
const byte *c_end= cur->rec + data_size; const byte *c_end= cur->rec + data_size;
static_assert(REC_N_OLD_EXTRA_BYTES == REC_N_NEW_EXTRA_BYTES + 1, "");
if (c <= insert_buf && c_end > insert_buf) if (c <= insert_buf && c_end > insert_buf)
c_end= insert_buf; c_end= insert_buf;
else if (c_end < next_rec &&
c_end >= next_rec - REC_N_OLD_EXTRA_BYTES + comp)
c_end= next_rec - REC_N_OLD_EXTRA_BYTES + comp;
else else
c_end= std::min<const byte*>(c_end, block->frame + srv_page_size - c_end= std::min<const byte*>(c_end, block->frame + srv_page_size -
PAGE_DIR - PAGE_DIR_SLOT_SIZE * PAGE_DIR - PAGE_DIR_SLOT_SIZE *
......
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