[MDEV-28168] Compressed page is read for non-compressed space during recovery Created: 2022-03-24 Updated: 2023-11-28 |
|
| Status: | Confirmed |
| Project: | MariaDB Server |
| Component/s: | Storage Engine - InnoDB |
| Affects Version/s: | 10.6 |
| Fix Version/s: | 10.4, 10.5, 10.6 |
| Type: | Bug | Priority: | Major |
| Reporter: | Vladislav Lesin | Assignee: | Vladislav Lesin |
| Resolution: | Unresolved | Votes: | 0 |
| Labels: | None | ||
| Attachments: |
|
||||||||
| Issue Links: |
|
||||||||
| Description |
|
During
buf_page_decrypt_after_read() does decompression only if node.space->is_compressed() && buf_page_is_compressed(dst_frame, flags) condition is true. For our case node.space->is_compressed() returns false as both FSP_FLAGS_FCRC32_GET_COMPRESSED_ALGO() and FSP_FLAGS_HAS_PAGE_COMPRESSION() are false. The space flags is 0x16. What means the space is not compressed. But the 15-th bit of FIL_PAGE_TYPE is set, what means the full_crc32 page is compressed, i.e. buf_page_is_compressed(dst_frame, flags) should return true. So we have compressed page on non-compressed space. The question is how is it possible? |
| Comments |
| Comment by Vladislav Lesin [ 2022-03-24 ] | ||||||||||||||||||||||||||||||||||||||||
|
In the attachment there is page itself page.bin | ||||||||||||||||||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2022-03-24 ] | ||||||||||||||||||||||||||||||||||||||||
|
I think that we need an rr replay of the server that was killed before the failed recovery. My current hypothesis is that this is repeatable with the default innodb_checksum_algorithm=full_crc32 and a test that runs something like this:
and kills the server during the execution of one of the ALTER TABLE statements. Disabling page_compressed should always cause the table to be rebuilt. It should be possible to enable page_compressed=1 instantly, by just updating the tablespace flags in the first page, because a page_compressed file may contain uncompressed pages. That is apparently being violated. Here, the first page does not identify the table as being in page_compressed=1 format, but a page is in the compressed format nevertheless. If I remember correctly, changes to page_compressed should not be reflected by any SYS_ tables, so this could theoretically also be a failure of DDL recovery, which currently largely depends on the DB_TRX_ID fields that are read from records of SYS_TABLES, SYS_INDEXES, and SYS_COLUMNS. | ||||||||||||||||||||||||||||||||||||||||
| Comment by Vladislav Lesin [ 2022-03-24 ] | ||||||||||||||||||||||||||||||||||||||||
|
The history if space->flags changing: 1. the space creating, the initial value is 0x16:
2. redo record type WRITE is applied, flags value 0x76, so bits 6,7 are set, what means FSP_FLAGS_FCRC32_GET_COMPRESSED_ALGO() should return 3, i.e. the space is compressed:
3. page 0 recovery, sets space flags to 0x16 again, i.e. cleans "compressed" flags:
And then the recovery of page 67 starts and the crash happens. The tablespace flags on disk is 0x16, i.e. the space without compression. It looks like the page was not flushed. When redo log record on (2) was parsed, the the correct space flags were set. And then, when the page 0 was read, the space flags was set from non-flushed before killing page 0, from FSP_HEADER_OFFSET + FSP_SPACE_FLAGS (0x36) offset. It looks like the issue is in recovery itself. | ||||||||||||||||||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2022-03-24 ] | ||||||||||||||||||||||||||||||||||||||||
|
That adjustment of fil_space_t::flags in recv_recover_page() may be redundant. If recv_sys_t::apply() wrote "Starting a batch to recover" instead of "Starting final batch", then I think that this is pretty clear: the tablespace flags in page 0 would only be set to the final value during a later batch. | ||||||||||||||||||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2022-03-25 ] | ||||||||||||||||||||||||||||||||||||||||
|
I suspect that this may have been broken ever since
Possibly, we should adjust all these fil_space_t fields once when initially parsing the redo log, before starting to apply any records to any data pages. In |