Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit3b558ac

Browse files
committed
Treat 2PC commit/abort the same as regular xacts in recovery.
There were several oversights in recovery code where COMMIT/ABORT PREPAREDrecords 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 byTom Lane and Andres Freund. The bug was always there, but was masked beforecommitd19bd29, because COMMIT PREPAREDalways created an extra regular transaction that was WAL-logged.Backpatch to all supported versions (older versions didn't have all thefeatures and therefore didn't have all of the above bugs).
1 parent850ebf2 commit3b558ac

File tree

2 files changed

+53
-10
lines changed

2 files changed

+53
-10
lines changed

‎src/backend/access/transam/xlog.c

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5431,11 +5431,21 @@ getRecordTimestamp(XLogRecord *record, TimestampTz *recordXtime)
54315431
*recordXtime= ((xl_xact_commit*)XLogRecGetData(record))->xact_time;
54325432
return true;
54335433
}
5434+
if (record->xl_rmid==RM_XACT_ID&&record_info==XLOG_XACT_COMMIT_PREPARED)
5435+
{
5436+
*recordXtime= ((xl_xact_commit_prepared*)XLogRecGetData(record))->crec.xact_time;
5437+
return true;
5438+
}
54345439
if (record->xl_rmid==RM_XACT_ID&&record_info==XLOG_XACT_ABORT)
54355440
{
54365441
*recordXtime= ((xl_xact_abort*)XLogRecGetData(record))->xact_time;
54375442
return true;
54385443
}
5444+
if (record->xl_rmid==RM_XACT_ID&&record_info==XLOG_XACT_ABORT_PREPARED)
5445+
{
5446+
*recordXtime= ((xl_xact_abort_prepared*)XLogRecGetData(record))->arec.xact_time;
5447+
return true;
5448+
}
54395449
return false;
54405450
}
54415451

@@ -5454,6 +5464,7 @@ recoveryStopsBefore(XLogRecord *record)
54545464
uint8record_info;
54555465
boolisCommit;
54565466
TimestampTzrecordXtime=0;
5467+
TransactionIdrecordXid;
54575468

54585469
/* Check if we should stop as soon as reaching consistency */
54595470
if (recoveryTarget==RECOVERY_TARGET_IMMEDIATE&&reachedConsistency)
@@ -5472,10 +5483,27 @@ recoveryStopsBefore(XLogRecord *record)
54725483
if (record->xl_rmid!=RM_XACT_ID)
54735484
return false;
54745485
record_info=record->xl_info& ~XLR_INFO_MASK;
5486+
54755487
if (record_info==XLOG_XACT_COMMIT_COMPACT||record_info==XLOG_XACT_COMMIT)
5488+
{
5489+
isCommit= true;
5490+
recordXid=record->xl_xid;
5491+
}
5492+
if (record_info==XLOG_XACT_COMMIT_PREPARED)
5493+
{
54765494
isCommit= true;
5495+
recordXid= ((xl_xact_commit_prepared*)XLogRecGetData(record))->xid;
5496+
}
54775497
elseif (record_info==XLOG_XACT_ABORT)
5498+
{
5499+
isCommit= false;
5500+
recordXid=record->xl_xid;
5501+
}
5502+
elseif (record_info==XLOG_XACT_ABORT_PREPARED)
5503+
{
54785504
isCommit= false;
5505+
recordXid= ((xl_xact_abort_prepared*)XLogRecGetData(record))->xid;
5506+
}
54795507
else
54805508
return false;
54815509

@@ -5490,7 +5518,7 @@ recoveryStopsBefore(XLogRecord *record)
54905518
* they complete. A higher numbered xid will complete before you about
54915519
* 50% of the time...
54925520
*/
5493-
stopsHere= (record->xl_xid==recoveryTargetXid);
5521+
stopsHere= (recordXid==recoveryTargetXid);
54945522
}
54955523

54965524
if (recoveryTarget==RECOVERY_TARGET_TIME&&
@@ -5510,7 +5538,7 @@ recoveryStopsBefore(XLogRecord *record)
55105538
if (stopsHere)
55115539
{
55125540
recoveryStopAfter= false;
5513-
recoveryStopXid=record->xl_xid;
5541+
recoveryStopXid=recordXid;
55145542
recoveryStopTime=recordXtime;
55155543
recoveryStopName[0]='\0';
55165544

@@ -5576,12 +5604,24 @@ recoveryStopsAfter(XLogRecord *record)
55765604
if (record->xl_rmid==RM_XACT_ID&&
55775605
(record_info==XLOG_XACT_COMMIT_COMPACT||
55785606
record_info==XLOG_XACT_COMMIT||
5579-
record_info==XLOG_XACT_ABORT))
5607+
record_info==XLOG_XACT_COMMIT_PREPARED||
5608+
record_info==XLOG_XACT_ABORT||
5609+
record_info==XLOG_XACT_ABORT_PREPARED))
55805610
{
5611+
TransactionIdrecordXid;
5612+
55815613
/* Update the last applied transaction timestamp */
55825614
if (getRecordTimestamp(record,&recordXtime))
55835615
SetLatestXTime(recordXtime);
55845616

5617+
/* Extract the XID of the committed/aborted transaction */
5618+
if (record_info==XLOG_XACT_COMMIT_PREPARED)
5619+
recordXid= ((xl_xact_commit_prepared*)XLogRecGetData(record))->xid;
5620+
elseif (record_info==XLOG_XACT_ABORT_PREPARED)
5621+
recordXid= ((xl_xact_abort_prepared*)XLogRecGetData(record))->xid;
5622+
else
5623+
recordXid=record->xl_xid;
5624+
55855625
/*
55865626
* There can be only one transaction end record with this exact
55875627
* transactionid
@@ -5592,21 +5632,24 @@ recoveryStopsAfter(XLogRecord *record)
55925632
* 50% of the time...
55935633
*/
55945634
if (recoveryTarget==RECOVERY_TARGET_XID&&recoveryTargetInclusive&&
5595-
record->xl_xid==recoveryTargetXid)
5635+
recordXid==recoveryTargetXid)
55965636
{
55975637
recoveryStopAfter= true;
5598-
recoveryStopXid=record->xl_xid;
5638+
recoveryStopXid=recordXid;
55995639
recoveryStopTime=recordXtime;
56005640
recoveryStopName[0]='\0';
56015641

5602-
if (record_info==XLOG_XACT_COMMIT_COMPACT||record_info==XLOG_XACT_COMMIT)
5642+
if (record_info==XLOG_XACT_COMMIT_COMPACT||
5643+
record_info==XLOG_XACT_COMMIT||
5644+
record_info==XLOG_XACT_COMMIT_PREPARED)
56035645
{
56045646
ereport(LOG,
56055647
(errmsg("recovery stopping after commit of transaction %u, time %s",
56065648
recoveryStopXid,
56075649
timestamptz_to_str(recoveryStopTime))));
56085650
}
5609-
elseif (record_info==XLOG_XACT_ABORT)
5651+
elseif (record_info==XLOG_XACT_ABORT||
5652+
record_info==XLOG_XACT_ABORT_PREPARED)
56105653
{
56115654
ereport(LOG,
56125655
(errmsg("recovery stopping after abort of transaction %u, time %s",
@@ -5719,7 +5762,8 @@ recoveryApplyDelay(XLogRecord *record)
57195762
record_info=record->xl_info& ~XLR_INFO_MASK;
57205763
if (!(record->xl_rmid==RM_XACT_ID&&
57215764
(record_info==XLOG_XACT_COMMIT_COMPACT||
5722-
record_info==XLOG_XACT_COMMIT)))
5765+
record_info==XLOG_XACT_COMMIT||
5766+
record_info==XLOG_XACT_COMMIT_PREPARED)))
57235767
return false;
57245768

57255769
if (!getRecordTimestamp(record,&xtime))

‎src/include/access/xact.h

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

187186
typedefstructxl_xact_commit_prepared

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp