Skip to content

Commit

Permalink
MDEV-30657 InnoDB: Not applying UNDO_APPEND due to corruption
Browse files Browse the repository at this point in the history
This almost completely reverts
commit acd23da and
retains a safe optimization:

recv_sys_t::parse(): Remove any old redo log records for the
truncated tablespace, to free up memory earlier.
If recovery consists of multiple batches, then recv_sys_t::apply()
will must invoke recv_sys_t::trim() again to avoid wrongly
applying old log records to an already truncated undo tablespace.
  • Loading branch information
dr-m committed Feb 15, 2023
1 parent 192427e commit 5300c0f
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 7 deletions.
12 changes: 9 additions & 3 deletions storage/innobase/include/log0recv.h
Original file line number Diff line number Diff line change
Expand Up @@ -266,9 +266,15 @@ struct recv_sys_t
@param lsn log sequence number of the shrink operation */
inline void trim(const page_id_t page_id, lsn_t lsn);

/** Truncated undo tablespace size for which truncate has been logged
(indexed by page_id_t::space() - srv_undo_space_id_start), or 0 */
unsigned truncated_undo_spaces[127];
/** Undo tablespaces for which truncate has been logged
(indexed by page_id_t::space() - srv_undo_space_id_start) */
struct trunc
{
/** log sequence number of FILE_CREATE, or 0 if none */
lsn_t lsn;
/** truncated size of the tablespace, or 0 if not truncated */
unsigned pages;
} truncated_undo_spaces[127];

public:
/** The contents of the doublewrite buffer */
Expand Down
16 changes: 12 additions & 4 deletions storage/innobase/log/log0recv.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1952,7 +1952,8 @@ bool recv_sys_t::parse(lsn_t checkpoint_lsn, store_t *store, bool apply)
/* The entire undo tablespace will be reinitialized by
innodb_undo_log_truncate=ON. Discard old log for all pages. */
trim({space_id, 0}, recovered_lsn);
truncated_undo_spaces[space_id - srv_undo_space_id_start]= page_no;
truncated_undo_spaces[space_id - srv_undo_space_id_start]=
{ recovered_lsn, page_no };
if (undo_space_trunc)
undo_space_trunc(space_id);
#endif
Expand Down Expand Up @@ -2677,15 +2678,22 @@ void recv_sys_t::apply(bool last_batch)

for (auto id= srv_undo_tablespaces_open; id--;)
{
if (unsigned pages= truncated_undo_spaces[id])
const trunc& t= truncated_undo_spaces[id];
if (t.lsn)
{
if (fil_space_t *space= fil_space_get(id + srv_undo_space_id_start))
/* The entire undo tablespace will be reinitialized by
innodb_undo_log_truncate=ON. Discard old log for all pages.
Even though we recv_sys_t::parse() already invoked trim(),
this will be needed in case recovery consists of multiple batches
(there was an invocation with !last_batch). */
trim({id + srv_undo_space_id_start, 0}, t.lsn);
if (fil_space_t *space = fil_space_get(id + srv_undo_space_id_start))
{
ut_ad(UT_LIST_GET_LEN(space->chain) == 1);
fil_node_t *file= UT_LIST_GET_FIRST(space->chain);
ut_ad(file->is_open());
os_file_truncate(file->name, file->handle,
os_offset_t{pages} << srv_page_size_shift, true);
os_offset_t{t.pages} << srv_page_size_shift, true);
}
}
}
Expand Down

0 comments on commit 5300c0f

Please sign in to comment.