Content-Length: 422322 | pFad | http://github.com/postgrespro/postgres/commit/de88ec6bf45477cd02905a8802e79868cb2ffdc3

03 Treat 2PC commit/abort the same as regular xacts in recovery. · postgrespro/postgres@de88ec6 · GitHub
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)








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/postgrespro/postgres/commit/de88ec6bf45477cd02905a8802e79868cb2ffdc3

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy