Skip to content

Commit de88ec6

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 8d49bf1 commit de88ec6

File tree

2 files changed

+27
-6
lines changed

2 files changed

+27
-6
lines changed

src/backend/access/transam/xlog.c

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5648,6 +5648,7 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
56485648
bool stopsHere;
56495649
uint8 record_info;
56505650
TimestampTz recordXtime;
5651+
TransactionId recordXid;
56515652
char recordRPName[MAXFNAMELEN];
56525653

56535654
/* We only consider stopping at COMMIT, ABORT or RESTORE POINT records */
@@ -5660,20 +5661,39 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
56605661

56615662
recordXactCommitData = (xl_xact_commit *) XLogRecGetData(record);
56625663
recordXtime = recordXactCommitData->xact_time;
5664+
recordXid = record->xl_xid;
5665+
}
5666+
else if (record->xl_rmid == RM_XACT_ID && record_info == XLOG_XACT_COMMIT_PREPARED)
5667+
{
5668+
xl_xact_commit_prepared *recordXactCommitData;
5669+
5670+
recordXactCommitData = (xl_xact_commit_prepared *) XLogRecGetData(record);
5671+
recordXtime = recordXactCommitData->crec.xact_time;
5672+
recordXid = recordXactCommitData->xid;
56635673
}
56645674
else if (record->xl_rmid == RM_XACT_ID && record_info == XLOG_XACT_ABORT)
56655675
{
56665676
xl_xact_abort *recordXactAbortData;
56675677

56685678
recordXactAbortData = (xl_xact_abort *) XLogRecGetData(record);
56695679
recordXtime = recordXactAbortData->xact_time;
5680+
recordXid = record->xl_xid;
5681+
}
5682+
else if (record->xl_rmid == RM_XACT_ID && record_info == XLOG_XACT_ABORT_PREPARED)
5683+
{
5684+
xl_xact_abort_prepared *recordXactAbortData;
5685+
5686+
recordXactAbortData = (xl_xact_abort_prepared *) XLogRecGetData(record);
5687+
recordXtime = recordXactAbortData->arec.xact_time;
5688+
recordXid = recordXactAbortData->xid;
56705689
}
56715690
else if (record->xl_rmid == RM_XLOG_ID && record_info == XLOG_RESTORE_POINT)
56725691
{
56735692
xl_restore_point *recordRestorePointData;
56745693

56755694
recordRestorePointData = (xl_restore_point *) XLogRecGetData(record);
56765695
recordXtime = recordRestorePointData->rp_time;
5696+
recordXid = InvalidTransactionId;
56775697
strlcpy(recordRPName, recordRestorePointData->rp_name, MAXFNAMELEN);
56785698
}
56795699
else
@@ -5702,7 +5722,7 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
57025722
* they complete. A higher numbered xid will complete before you about
57035723
* 50% of the time...
57045724
*/
5705-
stopsHere = (record->xl_xid == recoveryTargetXid);
5725+
stopsHere = (recordXid == recoveryTargetXid);
57065726
if (stopsHere)
57075727
*includeThis = recoveryTargetInclusive;
57085728
}
@@ -5737,11 +5757,12 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
57375757

57385758
if (stopsHere)
57395759
{
5740-
recoveryStopXid = record->xl_xid;
5760+
recoveryStopXid = recordXid;
57415761
recoveryStopTime = recordXtime;
57425762
recoveryStopAfter = *includeThis;
57435763

5744-
if (record_info == XLOG_XACT_COMMIT)
5764+
if (record_info == XLOG_XACT_COMMIT ||
5765+
record_info == XLOG_XACT_COMMIT_PREPARED)
57455766
{
57465767
if (recoveryStopAfter)
57475768
ereport(LOG,
@@ -5754,7 +5775,8 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
57545775
recoveryStopXid,
57555776
timestamptz_to_str(recoveryStopTime))));
57565777
}
5757-
else if (record_info == XLOG_XACT_ABORT)
5778+
else if (record_info == XLOG_XACT_ABORT ||
5779+
record_info == XLOG_XACT_ABORT_PREPARED)
57585780
{
57595781
if (recoveryStopAfter)
57605782
ereport(LOG,

src/include/access/xact.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,7 @@ typedef struct xl_xact_abort
165165
/*
166166
* COMMIT_PREPARED and ABORT_PREPARED are identical to COMMIT/ABORT records
167167
* except that we have to store the XID of the prepared transaction explicitly
168-
* --- the XID in the record header will be for the transaction doing the
169-
* COMMIT PREPARED or ABORT PREPARED command.
168+
* --- the XID in the record header will be invalid.
170169
*/
171170

172171
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