Re: Timeline switching with partial WAL records can break replica recovery - Mailing list pgsql-hackers

From D Laaren
Subject Re: Timeline switching with partial WAL records can break replica recovery
Date
Msg-id CAGWv16+hDSNThZeNf0qvUHHpmLE04jurrqHN7BbV1_uSN6tq+w@mail.gmail.com
Whole thread Raw
In response to Timeline switching with partial WAL records can break replica recovery  (D Laaren <dlaaren8@gmail.com>)
List pgsql-hackers
I've done more research and identified that replicas enter
an indefinite loop in the 'XLogReadPage' function.
The loop works as follows:
0. timeline N contains a partially written record with LSN = targetRecPtr;
1. In 'XLogReadPage' we attempt to read the next page, which has to
   contain the rest of the unfinished record;
2. In 'WaitForWALToBecomeAvailable' walrcv is requested to fetch
   records starting from LSN = targetRecPtr on timeline N + 1;
3. Walrcv retrieves data up to the end of page containing the end of
   timeline N + 1;
4. Then, in 'WaitForWALToBecomeAvailable', replica switches to
   XLOG_FROM_ARCHIVE state, and the function returns true;
5. Execution continues in 'XLogReadPage';
6. The page at addr = targetPagePtr is checked for validity, but we
   get an 'invalid magic number' error because walrcv hasn't retrieved
   this page;
7. Execution jumps to 'next_record_is_invalid' label;
8. Since we are in StandBy mode, the process retries from the beginning.

See the attachments for more colorful illustration this time =)

From my point of view, the first solution which I described in my
previous message still seems like a good choice.

I've also found the current solution in commit [1]. With all due
respect, but it seems to treat the symptom rather than the underlying
issue.

[1] https://github.com/postgres/postgres/commit/6cf1647d87e7cd423d71525a8759b75c4e4a47ec
Attachment

pgsql-hackers by date:

Previous
From: Konstantin Knizhnik
Date:
Subject: Re: Non-reproducible AIO failure
Next
From: Aleksander Alekseev
Date:
Subject: Re: Avoid possible dereference null pointer (src/backend/utils/cache/relcache.c)