Skip to content

Commit 1578d13

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 af9d516 commit 1578d13

File tree

2 files changed

+29
-6
lines changed

2 files changed

+29
-6
lines changed

src/backend/access/transam/xlog.c

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5880,6 +5880,7 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
58805880
bool stopsHere;
58815881
uint8 record_info;
58825882
TimestampTz recordXtime;
5883+
TransactionId recordXid;
58835884
char recordRPName[MAXFNAMELEN];
58845885

58855886
/* We only consider stopping at COMMIT, ABORT or RESTORE POINT records */
@@ -5892,27 +5893,47 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
58925893

58935894
recordXactCommitData = (xl_xact_commit_compact *) XLogRecGetData(record);
58945895
recordXtime = recordXactCommitData->xact_time;
5896+
recordXid = record->xl_xid;
58955897
}
58965898
else if (record->xl_rmid == RM_XACT_ID && record_info == XLOG_XACT_COMMIT)
58975899
{
58985900
xl_xact_commit *recordXactCommitData;
58995901

59005902
recordXactCommitData = (xl_xact_commit *) XLogRecGetData(record);
59015903
recordXtime = recordXactCommitData->xact_time;
5904+
recordXid = record->xl_xid;
5905+
}
5906+
else if (record->xl_rmid == RM_XACT_ID && record_info == XLOG_XACT_COMMIT_PREPARED)
5907+
{
5908+
xl_xact_commit_prepared *recordXactCommitData;
5909+
5910+
recordXactCommitData = (xl_xact_commit_prepared *) XLogRecGetData(record);
5911+
recordXtime = recordXactCommitData->crec.xact_time;
5912+
recordXid = recordXactCommitData->xid;
59025913
}
59035914
else if (record->xl_rmid == RM_XACT_ID && record_info == XLOG_XACT_ABORT)
59045915
{
59055916
xl_xact_abort *recordXactAbortData;
59065917

59075918
recordXactAbortData = (xl_xact_abort *) XLogRecGetData(record);
59085919
recordXtime = recordXactAbortData->xact_time;
5920+
recordXid = record->xl_xid;
5921+
}
5922+
else if (record->xl_rmid == RM_XACT_ID && record_info == XLOG_XACT_ABORT_PREPARED)
5923+
{
5924+
xl_xact_abort_prepared *recordXactAbortData;
5925+
5926+
recordXactAbortData = (xl_xact_abort_prepared *) XLogRecGetData(record);
5927+
recordXtime = recordXactAbortData->arec.xact_time;
5928+
recordXid = recordXactAbortData->xid;
59095929
}
59105930
else if (record->xl_rmid == RM_XLOG_ID && record_info == XLOG_RESTORE_POINT)
59115931
{
59125932
xl_restore_point *recordRestorePointData;
59135933

59145934
recordRestorePointData = (xl_restore_point *) XLogRecGetData(record);
59155935
recordXtime = recordRestorePointData->rp_time;
5936+
recordXid = InvalidTransactionId;
59165937
strlcpy(recordRPName, recordRestorePointData->rp_name, MAXFNAMELEN);
59175938
}
59185939
else
@@ -5941,7 +5962,7 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
59415962
* they complete. A higher numbered xid will complete before you about
59425963
* 50% of the time...
59435964
*/
5944-
stopsHere = (record->xl_xid == recoveryTargetXid);
5965+
stopsHere = (recordXid == recoveryTargetXid);
59455966
if (stopsHere)
59465967
*includeThis = recoveryTargetInclusive;
59475968
}
@@ -5976,11 +5997,13 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
59765997

59775998
if (stopsHere)
59785999
{
5979-
recoveryStopXid = record->xl_xid;
6000+
recoveryStopXid = recordXid;
59806001
recoveryStopTime = recordXtime;
59816002
recoveryStopAfter = *includeThis;
59826003

5983-
if (record_info == XLOG_XACT_COMMIT_COMPACT || record_info == XLOG_XACT_COMMIT)
6004+
if (record_info == XLOG_XACT_COMMIT_COMPACT ||
6005+
record_info == XLOG_XACT_COMMIT ||
6006+
record_info == XLOG_XACT_COMMIT_PREPARED)
59846007
{
59856008
if (recoveryStopAfter)
59866009
ereport(LOG,
@@ -5993,7 +6016,8 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
59936016
recoveryStopXid,
59946017
timestamptz_to_str(recoveryStopTime))));
59956018
}
5996-
else if (record_info == XLOG_XACT_ABORT)
6019+
else if (record_info == XLOG_XACT_ABORT ||
6020+
record_info == XLOG_XACT_ABORT_PREPARED)
59976021
{
59986022
if (recoveryStopAfter)
59996023
ereport(LOG,

src/include/access/xact.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,7 @@ typedef struct xl_xact_abort
177177
/*
178178
* COMMIT_PREPARED and ABORT_PREPARED are identical to COMMIT/ABORT records
179179
* except that we have to store the XID of the prepared transaction explicitly
180-
* --- the XID in the record header will be for the transaction doing the
181-
* COMMIT PREPARED or ABORT PREPARED command.
180+
* --- the XID in the record header will be invalid.
182181
*/
183182

184183
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