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)