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

Commite74e090

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 parent61e48ef commite74e090

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
@@ -5457,11 +5457,21 @@ getRecordTimestamp(XLogRecord *record, TimestampTz *recordXtime)
54575457
*recordXtime= ((xl_xact_commit*)XLogRecGetData(record))->xact_time;
54585458
return true;
54595459
}
5460+
if (record->xl_rmid==RM_XACT_ID&&record_info==XLOG_XACT_COMMIT_PREPARED)
5461+
{
5462+
*recordXtime= ((xl_xact_commit_prepared*)XLogRecGetData(record))->crec.xact_time;
5463+
return true;
5464+
}
54605465
if (record->xl_rmid==RM_XACT_ID&&record_info==XLOG_XACT_ABORT)
54615466
{
54625467
*recordXtime= ((xl_xact_abort*)XLogRecGetData(record))->xact_time;
54635468
return true;
54645469
}
5470+
if (record->xl_rmid==RM_XACT_ID&&record_info==XLOG_XACT_ABORT_PREPARED)
5471+
{
5472+
*recordXtime= ((xl_xact_abort_prepared*)XLogRecGetData(record))->arec.xact_time;
5473+
return true;
5474+
}
54655475
return false;
54665476
}
54675477

@@ -5480,6 +5490,7 @@ recoveryStopsBefore(XLogRecord *record)
54805490
uint8record_info;
54815491
boolisCommit;
54825492
TimestampTzrecordXtime=0;
5493+
TransactionIdrecordXid;
54835494

54845495
/* Check if we should stop as soon as reaching consistency */
54855496
if (recoveryTarget==RECOVERY_TARGET_IMMEDIATE&&reachedConsistency)
@@ -5498,10 +5509,27 @@ recoveryStopsBefore(XLogRecord *record)
54985509
if (record->xl_rmid!=RM_XACT_ID)
54995510
return false;
55005511
record_info=record->xl_info& ~XLR_INFO_MASK;
5512+
55015513
if (record_info==XLOG_XACT_COMMIT_COMPACT||record_info==XLOG_XACT_COMMIT)
5514+
{
5515+
isCommit= true;
5516+
recordXid=record->xl_xid;
5517+
}
5518+
if (record_info==XLOG_XACT_COMMIT_PREPARED)
5519+
{
55025520
isCommit= true;
5521+
recordXid= ((xl_xact_commit_prepared*)XLogRecGetData(record))->xid;
5522+
}
55035523
elseif (record_info==XLOG_XACT_ABORT)
5524+
{
5525+
isCommit= false;
5526+
recordXid=record->xl_xid;
5527+
}
5528+
elseif (record_info==XLOG_XACT_ABORT_PREPARED)
5529+
{
55045530
isCommit= false;
5531+
recordXid= ((xl_xact_abort_prepared*)XLogRecGetData(record))->xid;
5532+
}
55055533
else
55065534
return false;
55075535

@@ -5516,7 +5544,7 @@ recoveryStopsBefore(XLogRecord *record)
55165544
* they complete. A higher numbered xid will complete before you about
55175545
* 50% of the time...
55185546
*/
5519-
stopsHere= (record->xl_xid==recoveryTargetXid);
5547+
stopsHere= (recordXid==recoveryTargetXid);
55205548
}
55215549

55225550
if (recoveryTarget==RECOVERY_TARGET_TIME&&
@@ -5536,7 +5564,7 @@ recoveryStopsBefore(XLogRecord *record)
55365564
if (stopsHere)
55375565
{
55385566
recoveryStopAfter= false;
5539-
recoveryStopXid=record->xl_xid;
5567+
recoveryStopXid=recordXid;
55405568
recoveryStopTime=recordXtime;
55415569
recoveryStopName[0]='\0';
55425570

@@ -5602,12 +5630,24 @@ recoveryStopsAfter(XLogRecord *record)
56025630
if (record->xl_rmid==RM_XACT_ID&&
56035631
(record_info==XLOG_XACT_COMMIT_COMPACT||
56045632
record_info==XLOG_XACT_COMMIT||
5605-
record_info==XLOG_XACT_ABORT))
5633+
record_info==XLOG_XACT_COMMIT_PREPARED||
5634+
record_info==XLOG_XACT_ABORT||
5635+
record_info==XLOG_XACT_ABORT_PREPARED))
56065636
{
5637+
TransactionIdrecordXid;
5638+
56075639
/* Update the last applied transaction timestamp */
56085640
if (getRecordTimestamp(record,&recordXtime))
56095641
SetLatestXTime(recordXtime);
56105642

5643+
/* Extract the XID of the committed/aborted transaction */
5644+
if (record_info==XLOG_XACT_COMMIT_PREPARED)
5645+
recordXid= ((xl_xact_commit_prepared*)XLogRecGetData(record))->xid;
5646+
elseif (record_info==XLOG_XACT_ABORT_PREPARED)
5647+
recordXid= ((xl_xact_abort_prepared*)XLogRecGetData(record))->xid;
5648+
else
5649+
recordXid=record->xl_xid;
5650+
56115651
/*
56125652
* There can be only one transaction end record with this exact
56135653
* transactionid
@@ -5618,21 +5658,24 @@ recoveryStopsAfter(XLogRecord *record)
56185658
* 50% of the time...
56195659
*/
56205660
if (recoveryTarget==RECOVERY_TARGET_XID&&recoveryTargetInclusive&&
5621-
record->xl_xid==recoveryTargetXid)
5661+
recordXid==recoveryTargetXid)
56225662
{
56235663
recoveryStopAfter= true;
5624-
recoveryStopXid=record->xl_xid;
5664+
recoveryStopXid=recordXid;
56255665
recoveryStopTime=recordXtime;
56265666
recoveryStopName[0]='\0';
56275667

5628-
if (record_info==XLOG_XACT_COMMIT_COMPACT||record_info==XLOG_XACT_COMMIT)
5668+
if (record_info==XLOG_XACT_COMMIT_COMPACT||
5669+
record_info==XLOG_XACT_COMMIT||
5670+
record_info==XLOG_XACT_COMMIT_PREPARED)
56295671
{
56305672
ereport(LOG,
56315673
(errmsg("recovery stopping after commit of transaction %u, time %s",
56325674
recoveryStopXid,
56335675
timestamptz_to_str(recoveryStopTime))));
56345676
}
5635-
elseif (record_info==XLOG_XACT_ABORT)
5677+
elseif (record_info==XLOG_XACT_ABORT||
5678+
record_info==XLOG_XACT_ABORT_PREPARED)
56365679
{
56375680
ereport(LOG,
56385681
(errmsg("recovery stopping after abort of transaction %u, time %s",
@@ -5745,7 +5788,8 @@ recoveryApplyDelay(XLogRecord *record)
57455788
record_info=record->xl_info& ~XLR_INFO_MASK;
57465789
if (!(record->xl_rmid==RM_XACT_ID&&
57475790
(record_info==XLOG_XACT_COMMIT_COMPACT||
5748-
record_info==XLOG_XACT_COMMIT)))
5791+
record_info==XLOG_XACT_COMMIT||
5792+
record_info==XLOG_XACT_COMMIT_PREPARED)))
57495793
return false;
57505794

57515795
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