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

Commit8eace46

Browse files
committed
Fix race condition in reading commit timestamps
If a user requests the commit timestamp for a transaction old enoughthat its data is concurrently being truncated away by vacuum at just theright time, they would receive an ugly internal file-not-found errormessage from slru.c rather than the expected NULL return value.In a primary server, the window for the race is very small: the lookuphas to occur exactly between the two calls by vacuum, and there's not alot that happens between them (mostly just a multixact truncate). In astandby server, however, the window is larger because the truncation isexecuted as soon as the WAL record for it is replayed, but the advanceof the oldest-Xid is not executed until the next checkpoint record.To fix in the primary, simply reverse the order of operations invac_truncate_clog. To fix in the standby, augment the WAL truncationrecord so that the standby is aware of the new oldest-XID value and canapply the update immediately. WAL version bumped because of this.No backpatch, because of the low importance of the bug and its rarity.Author: Craig RingerReviewed-By: Petr Jelínek, Peter EisentrautDiscussion:https://postgr.es/m/CAMsr+YFhVtRQT1VAwC+WGbbxZZRzNou=N9Ed-FrCqkwQ8H8oJQ@mail.gmail.com
1 parent8b0fec9 commit8eace46

File tree

5 files changed

+34
-13
lines changed

5 files changed

+34
-13
lines changed

‎src/backend/access/rmgrdesc/committsdesc.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@ commit_ts_desc(StringInfo buf, XLogReaderState *record)
3333
}
3434
elseif (info==COMMIT_TS_TRUNCATE)
3535
{
36-
intpageno;
36+
xl_commit_ts_truncate*trunc= (xl_commit_ts_truncate*)rec;
3737

38-
memcpy(&pageno,rec,sizeof(int));
39-
appendStringInfo(buf,"%d",pageno);
38+
appendStringInfo(buf,"pageno %d, oldestXid %u",
39+
trunc->pageno,trunc->oldestXid);
4040
}
4141
elseif (info==COMMIT_TS_SETTS)
4242
{

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

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ static bool CommitTsPagePrecedes(int page1, int page2);
113113
staticvoidActivateCommitTs(void);
114114
staticvoidDeactivateCommitTs(void);
115115
staticvoidWriteZeroPageXlogRec(intpageno);
116-
staticvoidWriteTruncateXlogRec(intpageno);
116+
staticvoidWriteTruncateXlogRec(intpageno,TransactionIdoldestXid);
117117
staticvoidWriteSetTimestampXlogRec(TransactionIdmainxid,intnsubxids,
118118
TransactionId*subxids,TimestampTztimestamp,
119119
RepOriginIdnodeid);
@@ -824,7 +824,7 @@ TruncateCommitTs(TransactionId oldestXact)
824824
return;/* nothing to remove */
825825

826826
/* Write XLOG record */
827-
WriteTruncateXlogRec(cutoffPage);
827+
WriteTruncateXlogRec(cutoffPage,oldestXact);
828828

829829
/* Now we can remove the old CommitTs segment(s) */
830830
SimpleLruTruncate(CommitTsCtl,cutoffPage);
@@ -910,10 +910,15 @@ WriteZeroPageXlogRec(int pageno)
910910
* Write a TRUNCATE xlog record
911911
*/
912912
staticvoid
913-
WriteTruncateXlogRec(intpageno)
913+
WriteTruncateXlogRec(intpageno,TransactionIdoldestXid)
914914
{
915+
xl_commit_ts_truncatexlrec;
916+
917+
xlrec.pageno=pageno;
918+
xlrec.oldestXid=oldestXid;
919+
915920
XLogBeginInsert();
916-
XLogRegisterData((char*) (&pageno),sizeof(int));
921+
XLogRegisterData((char*) (&xlrec),SizeOfCommitTsTruncate);
917922
(void)XLogInsert(RM_COMMIT_TS_ID,COMMIT_TS_TRUNCATE);
918923
}
919924

@@ -967,17 +972,17 @@ commit_ts_redo(XLogReaderState *record)
967972
}
968973
elseif (info==COMMIT_TS_TRUNCATE)
969974
{
970-
intpageno;
975+
xl_commit_ts_truncate*trunc= (xl_commit_ts_truncate*)XLogRecGetData(record);
971976

972-
memcpy(&pageno,XLogRecGetData(record),sizeof(int));
977+
AdvanceOldestCommitTsXid(trunc->oldestXid);
973978

974979
/*
975980
* During XLOG replay, latest_page_number isn't set up yet; insert a
976981
* suitable value to bypass the sanity test in SimpleLruTruncate.
977982
*/
978-
CommitTsCtl->shared->latest_page_number=pageno;
983+
CommitTsCtl->shared->latest_page_number=trunc->pageno;
979984

980-
SimpleLruTruncate(CommitTsCtl,pageno);
985+
SimpleLruTruncate(CommitTsCtl,trunc->pageno);
981986
}
982987
elseif (info==COMMIT_TS_SETTS)
983988
{

‎src/backend/commands/vacuum.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1152,6 +1152,15 @@ vac_truncate_clog(TransactionId frozenXID,
11521152
if (bogus)
11531153
return;
11541154

1155+
/*
1156+
* Advance the oldest value for commit timestamps before truncating, so
1157+
* that if a user requests a timestamp for a transaction we're truncating
1158+
* away right after this point, they get NULL instead of an ugly "file not
1159+
* found" error from slru.c. This doesn't matter for xact/multixact
1160+
* because they are not subject to arbitrary lookups from users.
1161+
*/
1162+
AdvanceOldestCommitTsXid(frozenXID);
1163+
11551164
/*
11561165
* Truncate CLOG, multixact and CommitTs to the oldest computed value.
11571166
*/
@@ -1167,7 +1176,6 @@ vac_truncate_clog(TransactionId frozenXID,
11671176
*/
11681177
SetTransactionIdLimit(frozenXID,oldestxid_datoid);
11691178
SetMultiXactIdLimit(minMulti,minmulti_datoid);
1170-
AdvanceOldestCommitTsXid(frozenXID);
11711179
}
11721180

11731181

‎src/include/access/commit_ts.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,14 @@ typedef struct xl_commit_ts_set
6161
#defineSizeOfCommitTsSet(offsetof(xl_commit_ts_set, mainxid) + \
6262
sizeof(TransactionId))
6363

64+
typedefstructxl_commit_ts_truncate
65+
{
66+
intpageno;
67+
TransactionIdoldestXid;
68+
}xl_commit_ts_truncate;
69+
70+
#defineSizeOfCommitTsTruncate(offsetof(xl_commit_ts_truncate, oldestXid) + \
71+
sizeof(TransactionId))
6472

6573
externvoidcommit_ts_redo(XLogReaderState*record);
6674
externvoidcommit_ts_desc(StringInfobuf,XLogReaderState*record);

‎src/include/access/xlog_internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
/*
3232
* Each page of XLOG file has a header like this:
3333
*/
34-
#defineXLOG_PAGE_MAGIC0xD093/* can be used as WAL version indicator */
34+
#defineXLOG_PAGE_MAGIC0xD094/* can be used as WAL version indicator */
3535

3636
typedefstructXLogPageHeaderData
3737
{

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp