Skip to content

Commit 4ed8f09

Browse files
committed
Index SLRUs by 64-bit integers rather than by 32-bit integers
We've had repeated bugs in the area of handling SLRU wraparound in the past, some of which have caused data loss. Switching to an indexing system for SLRUs that does not wrap around should allow us to get rid of a whole bunch of problems and improve the overall reliability of the system. This particular patch however only changes the indexing and doesn't address the wraparound per se. This is going to be done in the following patches. Author: Maxim Orlov, Aleksander Alekseev, Alexander Korotkov, Teodor Sigaev Author: Nikita Glukhov, Pavel Borisov, Yura Sokolov Reviewed-by: Jacob Champion, Heikki Linnakangas, Alexander Korotkov Reviewed-by: Japin Li, Pavel Borisov, Tom Lane, Peter Eisentraut, Andres Freund Reviewed-by: Andrey Borodin, Dilip Kumar, Aleksander Alekseev Discussion: https://postgr.es/m/CACG%3DezZe1NQSCnfHOr78AtAZxJZeCvxrts0ygrxYwe%3DpyyjVWA%40mail.gmail.com Discussion: https://postgr.es/m/CAJ7c6TPDOYBYrnCAeyndkBktO0WG2xSdYduTF0nxq%2BvfkmTF5Q%40mail.gmail.com
1 parent a916b47 commit 4ed8f09

File tree

18 files changed

+303
-202
lines changed

18 files changed

+303
-202
lines changed

src/backend/access/rmgrdesc/clogdesc.c

+5-5
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,18 @@ clog_desc(StringInfo buf, XLogReaderState *record)
2525

2626
if (info == CLOG_ZEROPAGE)
2727
{
28-
int pageno;
28+
int64 pageno;
2929

30-
memcpy(&pageno, rec, sizeof(int));
31-
appendStringInfo(buf, "page %d", pageno);
30+
memcpy(&pageno, rec, sizeof(pageno));
31+
appendStringInfo(buf, "page %lld", (long long) pageno);
3232
}
3333
else if (info == CLOG_TRUNCATE)
3434
{
3535
xl_clog_truncate xlrec;
3636

3737
memcpy(&xlrec, rec, sizeof(xl_clog_truncate));
38-
appendStringInfo(buf, "page %d; oldestXact %u",
39-
xlrec.pageno, xlrec.oldestXact);
38+
appendStringInfo(buf, "page %lld; oldestXact %u",
39+
(long long) xlrec.pageno, xlrec.oldestXact);
4040
}
4141
}
4242

src/backend/access/rmgrdesc/committsdesc.c

+5-5
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,17 @@ commit_ts_desc(StringInfo buf, XLogReaderState *record)
2626

2727
if (info == COMMIT_TS_ZEROPAGE)
2828
{
29-
int pageno;
29+
int64 pageno;
3030

31-
memcpy(&pageno, rec, sizeof(int));
32-
appendStringInfo(buf, "%d", pageno);
31+
memcpy(&pageno, rec, sizeof(pageno));
32+
appendStringInfo(buf, "%lld", (long long) pageno);
3333
}
3434
else if (info == COMMIT_TS_TRUNCATE)
3535
{
3636
xl_commit_ts_truncate *trunc = (xl_commit_ts_truncate *) rec;
3737

38-
appendStringInfo(buf, "pageno %d, oldestXid %u",
39-
trunc->pageno, trunc->oldestXid);
38+
appendStringInfo(buf, "pageno %lld, oldestXid %u",
39+
(long long) trunc->pageno, trunc->oldestXid);
4040
}
4141
}
4242

src/backend/access/rmgrdesc/mxactdesc.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,10 @@ multixact_desc(StringInfo buf, XLogReaderState *record)
5555
if (info == XLOG_MULTIXACT_ZERO_OFF_PAGE ||
5656
info == XLOG_MULTIXACT_ZERO_MEM_PAGE)
5757
{
58-
int pageno;
58+
int64 pageno;
5959

60-
memcpy(&pageno, rec, sizeof(int));
61-
appendStringInfo(buf, "%d", pageno);
60+
memcpy(&pageno, rec, sizeof(pageno));
61+
appendStringInfo(buf, "%lld", (long long) pageno);
6262
}
6363
else if (info == XLOG_MULTIXACT_CREATE_ID)
6464
{

src/backend/access/transam/clog.c

+37-27
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,17 @@
6262
#define CLOG_XACTS_PER_PAGE (BLCKSZ * CLOG_XACTS_PER_BYTE)
6363
#define CLOG_XACT_BITMASK ((1 << CLOG_BITS_PER_XACT) - 1)
6464

65-
#define TransactionIdToPage(xid) ((xid) / (TransactionId) CLOG_XACTS_PER_PAGE)
65+
66+
/*
67+
* Although we return an int64 the actual value can't currently exceed
68+
* 0xFFFFFFFF/CLOG_XACTS_PER_PAGE.
69+
*/
70+
static inline int64
71+
TransactionIdToPage(TransactionId xid)
72+
{
73+
return xid / (int64) CLOG_XACTS_PER_PAGE;
74+
}
75+
6676
#define TransactionIdToPgIndex(xid) ((xid) % (TransactionId) CLOG_XACTS_PER_PAGE)
6777
#define TransactionIdToByte(xid) (TransactionIdToPgIndex(xid) / CLOG_XACTS_PER_BYTE)
6878
#define TransactionIdToBIndex(xid) ((xid) % (TransactionId) CLOG_XACTS_PER_BYTE)
@@ -89,24 +99,24 @@ static SlruCtlData XactCtlData;
8999
#define XactCtl (&XactCtlData)
90100

91101

92-
static int ZeroCLOGPage(int pageno, bool writeXlog);
93-
static bool CLOGPagePrecedes(int page1, int page2);
94-
static void WriteZeroPageXlogRec(int pageno);
95-
static void WriteTruncateXlogRec(int pageno, TransactionId oldestXact,
102+
static int ZeroCLOGPage(int64 pageno, bool writeXlog);
103+
static bool CLOGPagePrecedes(int64 page1, int64 page2);
104+
static void WriteZeroPageXlogRec(int64 pageno);
105+
static void WriteTruncateXlogRec(int64 pageno, TransactionId oldestXact,
96106
Oid oldestXactDb);
97107
static void TransactionIdSetPageStatus(TransactionId xid, int nsubxids,
98108
TransactionId *subxids, XidStatus status,
99-
XLogRecPtr lsn, int pageno,
109+
XLogRecPtr lsn, int64 pageno,
100110
bool all_xact_same_page);
101111
static void TransactionIdSetStatusBit(TransactionId xid, XidStatus status,
102112
XLogRecPtr lsn, int slotno);
103113
static void set_status_by_pages(int nsubxids, TransactionId *subxids,
104114
XidStatus status, XLogRecPtr lsn);
105115
static bool TransactionGroupUpdateXidStatus(TransactionId xid,
106-
XidStatus status, XLogRecPtr lsn, int pageno);
116+
XidStatus status, XLogRecPtr lsn, int64 pageno);
107117
static void TransactionIdSetPageStatusInternal(TransactionId xid, int nsubxids,
108118
TransactionId *subxids, XidStatus status,
109-
XLogRecPtr lsn, int pageno);
119+
XLogRecPtr lsn, int64 pageno);
110120

111121

112122
/*
@@ -162,7 +172,7 @@ void
162172
TransactionIdSetTreeStatus(TransactionId xid, int nsubxids,
163173
TransactionId *subxids, XidStatus status, XLogRecPtr lsn)
164174
{
165-
int pageno = TransactionIdToPage(xid); /* get page of parent */
175+
int64 pageno = TransactionIdToPage(xid); /* get page of parent */
166176
int i;
167177

168178
Assert(status == TRANSACTION_STATUS_COMMITTED ||
@@ -236,7 +246,7 @@ static void
236246
set_status_by_pages(int nsubxids, TransactionId *subxids,
237247
XidStatus status, XLogRecPtr lsn)
238248
{
239-
int pageno = TransactionIdToPage(subxids[0]);
249+
int64 pageno = TransactionIdToPage(subxids[0]);
240250
int offset = 0;
241251
int i = 0;
242252

@@ -245,7 +255,7 @@ set_status_by_pages(int nsubxids, TransactionId *subxids,
245255
while (i < nsubxids)
246256
{
247257
int num_on_page = 0;
248-
int nextpageno;
258+
int64 nextpageno;
249259

250260
do
251261
{
@@ -271,7 +281,7 @@ set_status_by_pages(int nsubxids, TransactionId *subxids,
271281
static void
272282
TransactionIdSetPageStatus(TransactionId xid, int nsubxids,
273283
TransactionId *subxids, XidStatus status,
274-
XLogRecPtr lsn, int pageno,
284+
XLogRecPtr lsn, int64 pageno,
275285
bool all_xact_same_page)
276286
{
277287
/* Can't use group update when PGPROC overflows. */
@@ -337,7 +347,7 @@ TransactionIdSetPageStatus(TransactionId xid, int nsubxids,
337347
static void
338348
TransactionIdSetPageStatusInternal(TransactionId xid, int nsubxids,
339349
TransactionId *subxids, XidStatus status,
340-
XLogRecPtr lsn, int pageno)
350+
XLogRecPtr lsn, int64 pageno)
341351
{
342352
int slotno;
343353
int i;
@@ -411,7 +421,7 @@ TransactionIdSetPageStatusInternal(TransactionId xid, int nsubxids,
411421
*/
412422
static bool
413423
TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status,
414-
XLogRecPtr lsn, int pageno)
424+
XLogRecPtr lsn, int64 pageno)
415425
{
416426
volatile PROC_HDR *procglobal = ProcGlobal;
417427
PGPROC *proc = MyProc;
@@ -637,7 +647,7 @@ TransactionIdSetStatusBit(TransactionId xid, XidStatus status, XLogRecPtr lsn, i
637647
XidStatus
638648
TransactionIdGetStatus(TransactionId xid, XLogRecPtr *lsn)
639649
{
640-
int pageno = TransactionIdToPage(xid);
650+
int64 pageno = TransactionIdToPage(xid);
641651
int byteno = TransactionIdToByte(xid);
642652
int bshift = TransactionIdToBIndex(xid) * CLOG_BITS_PER_XACT;
643653
int slotno;
@@ -697,7 +707,7 @@ CLOGShmemInit(void)
697707
XactCtl->PagePrecedes = CLOGPagePrecedes;
698708
SimpleLruInit(XactCtl, "Xact", CLOGShmemBuffers(), CLOG_LSNS_PER_PAGE,
699709
XactSLRULock, "pg_xact", LWTRANCHE_XACT_BUFFER,
700-
SYNC_HANDLER_CLOG);
710+
SYNC_HANDLER_CLOG, false);
701711
SlruPagePrecedesUnitTests(XactCtl, CLOG_XACTS_PER_PAGE);
702712
}
703713

@@ -734,7 +744,7 @@ BootStrapCLOG(void)
734744
* Control lock must be held at entry, and will be held at exit.
735745
*/
736746
static int
737-
ZeroCLOGPage(int pageno, bool writeXlog)
747+
ZeroCLOGPage(int64 pageno, bool writeXlog)
738748
{
739749
int slotno;
740750

@@ -754,7 +764,7 @@ void
754764
StartupCLOG(void)
755765
{
756766
TransactionId xid = XidFromFullTransactionId(ShmemVariableCache->nextXid);
757-
int pageno = TransactionIdToPage(xid);
767+
int64 pageno = TransactionIdToPage(xid);
758768

759769
LWLockAcquire(XactSLRULock, LW_EXCLUSIVE);
760770

@@ -773,7 +783,7 @@ void
773783
TrimCLOG(void)
774784
{
775785
TransactionId xid = XidFromFullTransactionId(ShmemVariableCache->nextXid);
776-
int pageno = TransactionIdToPage(xid);
786+
int64 pageno = TransactionIdToPage(xid);
777787

778788
LWLockAcquire(XactSLRULock, LW_EXCLUSIVE);
779789

@@ -838,7 +848,7 @@ CheckPointCLOG(void)
838848
void
839849
ExtendCLOG(TransactionId newestXact)
840850
{
841-
int pageno;
851+
int64 pageno;
842852

843853
/*
844854
* No work except at first XID of a page. But beware: just after
@@ -877,7 +887,7 @@ ExtendCLOG(TransactionId newestXact)
877887
void
878888
TruncateCLOG(TransactionId oldestXact, Oid oldestxid_datoid)
879889
{
880-
int cutoffPage;
890+
int64 cutoffPage;
881891

882892
/*
883893
* The cutoff point is the start of the segment containing oldestXact. We
@@ -930,7 +940,7 @@ TruncateCLOG(TransactionId oldestXact, Oid oldestxid_datoid)
930940
* don't optimize that edge case.
931941
*/
932942
static bool
933-
CLOGPagePrecedes(int page1, int page2)
943+
CLOGPagePrecedes(int64 page1, int64 page2)
934944
{
935945
TransactionId xid1;
936946
TransactionId xid2;
@@ -949,10 +959,10 @@ CLOGPagePrecedes(int page1, int page2)
949959
* Write a ZEROPAGE xlog record
950960
*/
951961
static void
952-
WriteZeroPageXlogRec(int pageno)
962+
WriteZeroPageXlogRec(int64 pageno)
953963
{
954964
XLogBeginInsert();
955-
XLogRegisterData((char *) (&pageno), sizeof(int));
965+
XLogRegisterData((char *) (&pageno), sizeof(pageno));
956966
(void) XLogInsert(RM_CLOG_ID, CLOG_ZEROPAGE);
957967
}
958968

@@ -963,7 +973,7 @@ WriteZeroPageXlogRec(int pageno)
963973
* in TruncateCLOG().
964974
*/
965975
static void
966-
WriteTruncateXlogRec(int pageno, TransactionId oldestXact, Oid oldestXactDb)
976+
WriteTruncateXlogRec(int64 pageno, TransactionId oldestXact, Oid oldestXactDb)
967977
{
968978
XLogRecPtr recptr;
969979
xl_clog_truncate xlrec;
@@ -991,10 +1001,10 @@ clog_redo(XLogReaderState *record)
9911001

9921002
if (info == CLOG_ZEROPAGE)
9931003
{
994-
int pageno;
1004+
int64 pageno;
9951005
int slotno;
9961006

997-
memcpy(&pageno, XLogRecGetData(record), sizeof(int));
1007+
memcpy(&pageno, XLogRecGetData(record), sizeof(pageno));
9981008

9991009
LWLockAcquire(XactSLRULock, LW_EXCLUSIVE);
10001010

0 commit comments

Comments
 (0)