MDEV-34156 InnoDB fails to apply the redo log for compressed tablespace

Problem:
=======
During recovery, InnoDB fails to apply the redo log for
compressed tablespace. The reason is that InnoDB assumes
that pages has been freed while applying the redo log for it.
During multiple scan of redo logs, InnoDB stores the freed
page information when it have sufficient buffer pool pages.
Once it ran out of memory, InnoDB doesn't store freed page
information. But InnoDB assigns the freed page ranges to tablespace
in recv_init_crash_recovery_spaces() even though
InnoDB doesn't have complete freed range information.
While applying the redo log, InnoDB wrongly assumes that page
has been freed and it could lead to corruption of tablespace.
This issue is caused by commit 941af1fa (MDEV-31803)
and commit 2f9e2647 (MDEV-29911).

Solution:
========
During recovery, set recovery size and freed page information
for all tablespace irrespective of memory.
parent b81d7173
......@@ -2768,8 +2768,7 @@ recv_sys_t::parse_mtr_result recv_sys_t::parse(source &l, bool if_exists)
case INIT_PAGE:
last_offset= FIL_PAGE_TYPE;
free_or_init_page:
if (store)
store_freed_or_init_rec(id, (b & 0x70) == FREE_PAGE);
store_freed_or_init_rec(id, (b & 0x70) == FREE_PAGE);
if (UNIV_UNLIKELY(rlen != 0))
goto record_corrupted;
copy_if_needed:
......@@ -2833,7 +2832,7 @@ recv_sys_t::parse_mtr_result recv_sys_t::parse(source &l, bool if_exists)
{
if (UNIV_UNLIKELY(rlen + last_offset > srv_page_size))
goto record_corrupted;
if (store && UNIV_UNLIKELY(!page_no) && file_checkpoint)
if (UNIV_UNLIKELY(!page_no) && file_checkpoint)
{
const bool has_size= last_offset <= FSP_HEADER_OFFSET + FSP_SIZE &&
last_offset + rlen >= FSP_HEADER_OFFSET + FSP_SIZE + 4;
......
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