Re: BUG #17731: Server doesn't start after abnormal shutdown while creating unlogged tables

Поиск
Список
Период
Сортировка
От Karina Litskevich
Тема Re: BUG #17731: Server doesn't start after abnormal shutdown while creating unlogged tables
Дата
Msg-id CACiT8ibXxDpJHO0gFtCXxD5nShnByW5OS37H2hPgjsoxBKD_Xw@mail.gmail.com
обсуждение исходный текст
Ответ на BUG #17731: Server doesn't start after abnormal shutdown while creating unlogged tables  (PG Bug reporting form <noreply@postgresql.org>)
Ответы Re: BUG #17731: Server doesn't start after abnormal shutdown while creating unlogged tables  (Kyotaro Horiguchi <horikyota.ntt@gmail.com>)
Re: BUG #17731: Server doesn't start after abnormal shutdown while creating unlogged tables  (Michael Paquier <michael@paquier.xyz>)
Список pgsql-bugs
For unlogged tables and indexes init forks are created to simulate truncate on
server startup. In StartupXLOG() every main fork, for which corresponding init
fork exists, is deleted before replaying WAL, and then new main fork is created
by copying init fork:

ResetUnloggedRelations(UNLOGGED_RELATION_CLEANUP);
...
PerformWalRecovery();
...
ResetUnloggedRelations(UNLOGGED_RELATION_INIT);

So in case before WAL recovery main fork exists and init fork isn't, and during
recovery init fork is created, we get this problem. The second
ResetUnloggedRelations() call sees just created init fork and tries to create a
main fork from it expecting that the old main fork was already deleted by the
first ResetUnloggedRelations() call, but it wasn't because the main fork hasn't
corresponding init fork at that moment yet.

If you try to start server again, it will start successfully, as this time both
init and main forks will present from the beginning.

The situation, when main fork of the unlogged table is present but init fork is
not, can happen because main fork file isn't actually being deleted when table
is dropped. It's deletion is being postponed until the next checkpoint. See
comment before mdunlink():

/* ...
 *           Leaving the empty file in place prevents that relfilenumber
 * from being reused.  The scenario this protects us from is:
 * 1. We delete a relation (and commit, and actually remove its file).
 * 2. We create a new relation, which by chance gets the same relfilenumber as
 *   the just-deleted one (OIDs must've wrapped around for that to happen).
 * 3. We crash before another checkpoint occurs.
 * ...
 */

Theoretically, this applies to all versions, but the script somehow doesn't lead
to an error on REL_11_STABLE. I haven't investigated it yet.

I see two solutions: 1) keep init fork files until the next checkpoint as well
as main fork files, 2) ignore (rewrite if exists) presence of an empty main
fork file when copying from init fork. I found the latter less elegant so I
implemented the first one. The patch is attached.


Best regards,
Karina Litskevich
Postgres Professional: http://postgrespro.com/

Вложения

В списке pgsql-bugs по дате отправления:

Предыдущее
От: Alexander Korotkov
Дата:
Сообщение: Re: BUG #17847: Unaligned memory access in ltree_gist
Следующее
От: PG Bug reporting form
Дата:
Сообщение: BUG #17907: PostgresSQL 15.x contains OpenSSL DLLs (vulnerable to CVE-2023-0464, CVE-2023-0465 & CVE-2023-0466)