Skip to content

Commit 8049839

Browse files
committed
Treat 2PC commit/abort the same as regular xacts in recovery.
There were several oversights in recovery code where COMMIT/ABORT PREPARED records were ignored: * pg_last_xact_replay_timestamp() (wasn't updated for 2PC commits) * recovery_min_apply_delay (2PC commits were applied immediately) * recovery_target_xid (recovery would not stop if the XID used 2PC) The first of those was reported by Sergiy Zuban in bug #11032, analyzed by Tom Lane and Andres Freund. The bug was always there, but was masked before commit d19bd29, because COMMIT PREPARED always created an extra regular transaction that was WAL-logged. Backpatch to all supported versions (older versions didn't have all the features and therefore didn't have all of the above bugs).
1 parent ccf2b00 commit 8049839

File tree

2 files changed

+24
-5
lines changed

2 files changed

+24
-5
lines changed

src/backend/access/transam/xlog.c

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5520,6 +5520,7 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
55205520
bool stopsHere;
55215521
uint8 record_info;
55225522
TimestampTz recordXtime;
5523+
TransactionId recordXid;
55235524

55245525
/* We only consider stopping at COMMIT or ABORT records */
55255526
if (record->xl_rmid != RM_XACT_ID)
@@ -5531,13 +5532,31 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
55315532

55325533
recordXactCommitData = (xl_xact_commit *) XLogRecGetData(record);
55335534
recordXtime = recordXactCommitData->xact_time;
5535+
recordXid = record->xl_xid;
5536+
}
5537+
else if (record->xl_rmid == RM_XACT_ID && record_info == XLOG_XACT_COMMIT_PREPARED)
5538+
{
5539+
xl_xact_commit_prepared *recordXactCommitData;
5540+
5541+
recordXactCommitData = (xl_xact_commit_prepared *) XLogRecGetData(record);
5542+
recordXtime = recordXactCommitData->crec.xact_time;
5543+
recordXid = recordXactCommitData->xid;
55345544
}
55355545
else if (record_info == XLOG_XACT_ABORT)
55365546
{
55375547
xl_xact_abort *recordXactAbortData;
55385548

55395549
recordXactAbortData = (xl_xact_abort *) XLogRecGetData(record);
55405550
recordXtime = recordXactAbortData->xact_time;
5551+
recordXid = record->xl_xid;
5552+
}
5553+
else if (record->xl_rmid == RM_XACT_ID && record_info == XLOG_XACT_ABORT_PREPARED)
5554+
{
5555+
xl_xact_abort_prepared *recordXactAbortData;
5556+
5557+
recordXactAbortData = (xl_xact_abort_prepared *) XLogRecGetData(record);
5558+
recordXtime = recordXactAbortData->arec.xact_time;
5559+
recordXid = recordXactAbortData->xid;
55415560
}
55425561
else
55435562
return false;
@@ -5560,7 +5579,7 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
55605579
* they complete. A higher numbered xid will complete before you about
55615580
* 50% of the time...
55625581
*/
5563-
stopsHere = (record->xl_xid == recoveryTargetXid);
5582+
stopsHere = (recordXid == recoveryTargetXid);
55645583
if (stopsHere)
55655584
*includeThis = recoveryTargetInclusive;
55665585
}
@@ -5581,11 +5600,12 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
55815600

55825601
if (stopsHere)
55835602
{
5584-
recoveryStopXid = record->xl_xid;
5603+
recoveryStopXid = recordXid;
55855604
recoveryStopTime = recordXtime;
55865605
recoveryStopAfter = *includeThis;
55875606

5588-
if (record_info == XLOG_XACT_COMMIT)
5607+
if (record_info == XLOG_XACT_COMMIT ||
5608+
record_info == XLOG_XACT_COMMIT_PREPARED)
55895609
{
55905610
if (recoveryStopAfter)
55915611
ereport(LOG,

src/include/access/xact.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,7 @@ typedef struct xl_xact_abort
144144
/*
145145
* COMMIT_PREPARED and ABORT_PREPARED are identical to COMMIT/ABORT records
146146
* except that we have to store the XID of the prepared transaction explicitly
147-
* --- the XID in the record header will be for the transaction doing the
148-
* COMMIT PREPARED or ABORT PREPARED command.
147+
* --- the XID in the record header will be invalid.
149148
*/
150149

151150
typedef struct xl_xact_commit_prepared

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy