Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitdb59108

Browse files
committed
Fix recovery of 2PC transaction during crash recovery
A crash in the middle of a checkpoint with some two-phase state dataalready flushed to disk by this checkpoint could cause a follow-up crashrecovery to recover twice the same transaction, once from what has beenfound in pg_twophase/ at the beginning of recovery and a second timewhen replaying its corresponding record.This would lead to FATAL failures in the startup process duringrecovery, where the same transaction would have a state recovered twiceinstead of once:LOG: recovering prepared transaction 731 from shared memoryLOG: recovering prepared transaction 731 from shared memoryFATAL: lock ExclusiveLock on object 731/0/0 is already heldThis issue is fixed by skipping the addition of any 2PC state comingfrom a record whose equivalent 2PC state file has already been loaded inTwoPhaseState at the beginning of recovery by restoreTwoPhaseData(),which is OK as long as the system has not reached a consistent state.The timing to get a messed up recovery processing is very racy, andwould very unlikely happen. The thread that has reported the issue hasdemonstrated the bug using injection points to force a PANIC in themiddle of a checkpoint.Issue introduced in728bd99, so backpatch all the way down.Reported-by: "suyu.cmj" <mengjuan.cmj@alibaba-inc.com>Author: "suyu.cmj" <mengjuan.cmj@alibaba-inc.com>Author: Michael PaquierDiscussion:https://postgr.es/m/109e6994-b971-48cb-84f6-829646f18b4c.mengjuan.cmj@alibaba-inc.comBackpatch-through: 11
1 parentbdaaf1b commitdb59108

File tree

1 file changed

+33
-0
lines changed

1 file changed

+33
-0
lines changed

‎src/backend/access/transam/twophase.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2443,6 +2443,39 @@ PrepareRedoAdd(char *buf, XLogRecPtr start_lsn,
24432443
* that it got added in the redo phase
24442444
*/
24452445

2446+
/*
2447+
* In the event of a crash while a checkpoint was running, it may be
2448+
* possible that some two-phase data found its way to disk while its
2449+
* corresponding record needs to be replayed in the follow-up recovery.
2450+
* As the 2PC data was on disk, it has already been restored at the
2451+
* beginning of recovery with restoreTwoPhaseData(), so skip this record
2452+
* to avoid duplicates in TwoPhaseState. If a consistent state has been
2453+
* reached, the record is added to TwoPhaseState and it should have no
2454+
* corresponding file in pg_twophase.
2455+
*/
2456+
if (!XLogRecPtrIsInvalid(start_lsn))
2457+
{
2458+
charpath[MAXPGPATH];
2459+
2460+
TwoPhaseFilePath(path,hdr->xid);
2461+
2462+
if (access(path,F_OK)==0)
2463+
{
2464+
ereport(reachedConsistency ?ERROR :WARNING,
2465+
(errmsg("could not recover two-phase state file for transaction %u",
2466+
hdr->xid),
2467+
errdetail("Two-phase state file has been found in WAL record %X/%X, but this transaction has already been restored from disk.",
2468+
(uint32) (start_lsn >>32),
2469+
(uint32)start_lsn)));
2470+
return;
2471+
}
2472+
2473+
if (errno!=ENOENT)
2474+
ereport(ERROR,
2475+
(errcode_for_file_access(),
2476+
errmsg("could not access file \"%s\": %m",path)));
2477+
}
2478+
24462479
/* Get a free gxact from the freelist */
24472480
if (TwoPhaseState->freeGXacts==NULL)
24482481
ereport(ERROR,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp