Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 465883b

Browse files
Introduce compact WAL record for the common case of commit (non-DDL).
XLOG_XACT_COMMIT_COMPACT leaves out invalidation messages and relfilenodes, saving considerable space for the vast majority of transaction commits. XLOG_XACT_COMMIT keeps same definition as XLOG_PAGE_MAGIC 0xD067 and earlier. Leonardo Francalanci and Simon Riggs
1 parent 6f3efa7 commit 465883b

File tree

4 files changed

+192
-81
lines changed

4 files changed

+192
-81
lines changed

src/backend/access/transam/xact.c

Lines changed: 169 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -962,25 +962,9 @@ RecordTransactionCommit(void)
962962
/*
963963
* Begin commit critical section and insert the commit XLOG record.
964964
*/
965-
XLogRecData rdata[4];
966-
int lastrdata = 0;
967-
xl_xact_commit xlrec;
968-
969965
/* Tell bufmgr and smgr to prepare for commit */
970966
BufmgrCommit();
971967

972-
/*
973-
* Set flags required for recovery processing of commits.
974-
*/
975-
xlrec.xinfo = 0;
976-
if (RelcacheInitFileInval)
977-
xlrec.xinfo |= XACT_COMPLETION_UPDATE_RELCACHE_FILE;
978-
if (forceSyncCommit)
979-
xlrec.xinfo |= XACT_COMPLETION_FORCE_SYNC_COMMIT;
980-
981-
xlrec.dbId = MyDatabaseId;
982-
xlrec.tsId = MyDatabaseTableSpace;
983-
984968
/*
985969
* Mark ourselves as within our "commit critical section". This
986970
* forces any concurrent checkpoint to wait until we've updated
@@ -1002,43 +986,88 @@ RecordTransactionCommit(void)
1002986
MyProc->inCommit = true;
1003987

1004988
SetCurrentTransactionStopTimestamp();
1005-
xlrec.xact_time = xactStopTimestamp;
1006-
xlrec.nrels = nrels;
1007-
xlrec.nsubxacts = nchildren;
1008-
xlrec.nmsgs = nmsgs;
1009-
rdata[0].data = (char *) (&xlrec);
1010-
rdata[0].len = MinSizeOfXactCommit;
1011-
rdata[0].buffer = InvalidBuffer;
1012-
/* dump rels to delete */
1013-
if (nrels > 0)
1014-
{
1015-
rdata[0].next = &(rdata[1]);
1016-
rdata[1].data = (char *) rels;
1017-
rdata[1].len = nrels * sizeof(RelFileNode);
1018-
rdata[1].buffer = InvalidBuffer;
1019-
lastrdata = 1;
1020-
}
1021-
/* dump committed child Xids */
1022-
if (nchildren > 0)
989+
990+
/*
991+
* Do we need the long commit record? If not, use the compact format.
992+
*/
993+
if (nrels > 0 || nmsgs > 0 || RelcacheInitFileInval || forceSyncCommit)
1023994
{
1024-
rdata[lastrdata].next = &(rdata[2]);
1025-
rdata[2].data = (char *) children;
1026-
rdata[2].len = nchildren * sizeof(TransactionId);
1027-
rdata[2].buffer = InvalidBuffer;
1028-
lastrdata = 2;
995+
XLogRecData rdata[4];
996+
int lastrdata = 0;
997+
xl_xact_commit xlrec;
998+
/*
999+
* Set flags required for recovery processing of commits.
1000+
*/
1001+
xlrec.xinfo = 0;
1002+
if (RelcacheInitFileInval)
1003+
xlrec.xinfo |= XACT_COMPLETION_UPDATE_RELCACHE_FILE;
1004+
if (forceSyncCommit)
1005+
xlrec.xinfo |= XACT_COMPLETION_FORCE_SYNC_COMMIT;
1006+
1007+
xlrec.dbId = MyDatabaseId;
1008+
xlrec.tsId = MyDatabaseTableSpace;
1009+
1010+
xlrec.xact_time = xactStopTimestamp;
1011+
xlrec.nrels = nrels;
1012+
xlrec.nsubxacts = nchildren;
1013+
xlrec.nmsgs = nmsgs;
1014+
rdata[0].data = (char *) (&xlrec);
1015+
rdata[0].len = MinSizeOfXactCommit;
1016+
rdata[0].buffer = InvalidBuffer;
1017+
/* dump rels to delete */
1018+
if (nrels > 0)
1019+
{
1020+
rdata[0].next = &(rdata[1]);
1021+
rdata[1].data = (char *) rels;
1022+
rdata[1].len = nrels * sizeof(RelFileNode);
1023+
rdata[1].buffer = InvalidBuffer;
1024+
lastrdata = 1;
1025+
}
1026+
/* dump committed child Xids */
1027+
if (nchildren > 0)
1028+
{
1029+
rdata[lastrdata].next = &(rdata[2]);
1030+
rdata[2].data = (char *) children;
1031+
rdata[2].len = nchildren * sizeof(TransactionId);
1032+
rdata[2].buffer = InvalidBuffer;
1033+
lastrdata = 2;
1034+
}
1035+
/* dump shared cache invalidation messages */
1036+
if (nmsgs > 0)
1037+
{
1038+
rdata[lastrdata].next = &(rdata[3]);
1039+
rdata[3].data = (char *) invalMessages;
1040+
rdata[3].len = nmsgs * sizeof(SharedInvalidationMessage);
1041+
rdata[3].buffer = InvalidBuffer;
1042+
lastrdata = 3;
1043+
}
1044+
rdata[lastrdata].next = NULL;
1045+
1046+
(void) XLogInsert(RM_XACT_ID, XLOG_XACT_COMMIT, rdata);
10291047
}
1030-
/* dump shared cache invalidation messages */
1031-
if (nmsgs > 0)
1048+
else
10321049
{
1033-
rdata[lastrdata].next = &(rdata[3]);
1034-
rdata[3].data = (char *) invalMessages;
1035-
rdata[3].len = nmsgs * sizeof(SharedInvalidationMessage);
1036-
rdata[3].buffer = InvalidBuffer;
1037-
lastrdata = 3;
1038-
}
1039-
rdata[lastrdata].next = NULL;
1050+
XLogRecData rdata[2];
1051+
int lastrdata = 0;
1052+
xl_xact_commit_compact xlrec;
1053+
xlrec.xact_time = xactStopTimestamp;
1054+
xlrec.nsubxacts = nchildren;
1055+
rdata[0].data = (char *) (&xlrec);
1056+
rdata[0].len = MinSizeOfXactCommitCompact;
1057+
rdata[0].buffer = InvalidBuffer;
1058+
/* dump committed child Xids */
1059+
if (nchildren > 0)
1060+
{
1061+
rdata[0].next = &(rdata[1]);
1062+
rdata[1].data = (char *) children;
1063+
rdata[1].len = nchildren * sizeof(TransactionId);
1064+
rdata[1].buffer = InvalidBuffer;
1065+
lastrdata = 1;
1066+
}
1067+
rdata[lastrdata].next = NULL;
10401068

1041-
(void) XLogInsert(RM_XACT_ID, XLOG_XACT_COMMIT, rdata);
1069+
(void) XLogInsert(RM_XACT_ID, XLOG_XACT_COMMIT_COMPACT, rdata);
1070+
}
10421071
}
10431072

10441073
/*
@@ -4441,19 +4470,17 @@ xactGetCommittedChildren(TransactionId **ptr)
44414470
* actions for which the order of execution is critical.
44424471
*/
44434472
static void
4444-
xact_redo_commit(xl_xact_commit *xlrec, TransactionId xid, XLogRecPtr lsn)
4473+
xact_redo_commit_internal(TransactionId xid, XLogRecPtr lsn,
4474+
TransactionId *sub_xids, int nsubxacts,
4475+
SharedInvalidationMessage *inval_msgs, int nmsgs,
4476+
RelFileNode *xnodes, int nrels,
4477+
Oid dbId, Oid tsId,
4478+
uint32 xinfo)
44454479
{
4446-
TransactionId *sub_xids;
4447-
SharedInvalidationMessage *inval_msgs;
44484480
TransactionId max_xid;
44494481
int i;
44504482

4451-
/* subxid array follows relfilenodes */
4452-
sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
4453-
/* invalidation messages array follows subxids */
4454-
inval_msgs = (SharedInvalidationMessage *) &(sub_xids[xlrec->nsubxacts]);
4455-
4456-
max_xid = TransactionIdLatest(xid, xlrec->nsubxacts, sub_xids);
4483+
max_xid = TransactionIdLatest(xid, nsubxacts, sub_xids);
44574484

44584485
/*
44594486
* Make sure nextXid is beyond any XID mentioned in the record.
@@ -4476,7 +4503,7 @@ xact_redo_commit(xl_xact_commit *xlrec, TransactionId xid, XLogRecPtr lsn)
44764503
/*
44774504
* Mark the transaction committed in pg_clog.
44784505
*/
4479-
TransactionIdCommitTree(xid, xlrec->nsubxacts, sub_xids);
4506+
TransactionIdCommitTree(xid, nsubxacts, sub_xids);
44804507
}
44814508
else
44824509
{
@@ -4500,41 +4527,41 @@ xact_redo_commit(xl_xact_commit *xlrec, TransactionId xid, XLogRecPtr lsn)
45004527
* bits set on changes made by transactions that haven't yet
45014528
* recovered. It's unlikely but it's good to be safe.
45024529
*/
4503-
TransactionIdAsyncCommitTree(xid, xlrec->nsubxacts, sub_xids, lsn);
4530+
TransactionIdAsyncCommitTree(xid, nsubxacts, sub_xids, lsn);
45044531

45054532
/*
45064533
* We must mark clog before we update the ProcArray.
45074534
*/
4508-
ExpireTreeKnownAssignedTransactionIds(xid, xlrec->nsubxacts, sub_xids, max_xid);
4535+
ExpireTreeKnownAssignedTransactionIds(xid, nsubxacts, sub_xids, max_xid);
45094536

45104537
/*
45114538
* Send any cache invalidations attached to the commit. We must
45124539
* maintain the same order of invalidation then release locks as
45134540
* occurs in CommitTransaction().
45144541
*/
4515-
ProcessCommittedInvalidationMessages(inval_msgs, xlrec->nmsgs,
4516-
XactCompletionRelcacheInitFileInval(xlrec),
4517-
xlrec->dbId, xlrec->tsId);
4542+
ProcessCommittedInvalidationMessages(inval_msgs, nmsgs,
4543+
XactCompletionRelcacheInitFileInval(xinfo),
4544+
dbId, tsId);
45184545

45194546
/*
45204547
* Release locks, if any. We do this for both two phase and normal one
45214548
* phase transactions. In effect we are ignoring the prepare phase and
45224549
* just going straight to lock release.
45234550
*/
4524-
StandbyReleaseLockTree(xid, xlrec->nsubxacts, sub_xids);
4551+
StandbyReleaseLockTree(xid, nsubxacts, sub_xids);
45254552
}
45264553

45274554
/* Make sure files supposed to be dropped are dropped */
4528-
for (i = 0; i < xlrec->nrels; i++)
4555+
for (i = 0; i < nrels; i++)
45294556
{
4530-
SMgrRelation srel = smgropen(xlrec->xnodes[i], InvalidBackendId);
4557+
SMgrRelation srel = smgropen(xnodes[i], InvalidBackendId);
45314558
ForkNumber fork;
45324559

45334560
for (fork = 0; fork <= MAX_FORKNUM; fork++)
45344561
{
45354562
if (smgrexists(srel, fork))
45364563
{
4537-
XLogDropRelation(xlrec->xnodes[i], fork);
4564+
XLogDropRelation(xnodes[i], fork);
45384565
smgrdounlink(srel, fork, true);
45394566
}
45404567
}
@@ -4553,8 +4580,46 @@ xact_redo_commit(xl_xact_commit *xlrec, TransactionId xid, XLogRecPtr lsn)
45534580
* to reduce that problem window, for any user that requested
45544581
* ForceSyncCommit().
45554582
*/
4556-
if (XactCompletionForceSyncCommit(xlrec))
4583+
if (XactCompletionForceSyncCommit(xinfo))
45574584
XLogFlush(lsn);
4585+
4586+
}
4587+
/*
4588+
* Utility function to call xact_redo_commit_internal after breaking down xlrec
4589+
*/
4590+
static void
4591+
xact_redo_commit(xl_xact_commit *xlrec,
4592+
TransactionId xid, XLogRecPtr lsn)
4593+
{
4594+
TransactionId *subxacts;
4595+
SharedInvalidationMessage *inval_msgs;
4596+
4597+
/* subxid array follows relfilenodes */
4598+
subxacts = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
4599+
/* invalidation messages array follows subxids */
4600+
inval_msgs = (SharedInvalidationMessage *) &(subxacts[xlrec->nsubxacts]);
4601+
4602+
xact_redo_commit_internal(xid, lsn, subxacts, xlrec->nsubxacts,
4603+
inval_msgs, xlrec->nmsgs,
4604+
xlrec->xnodes, xlrec->nrels,
4605+
xlrec->dbId,
4606+
xlrec->tsId,
4607+
xlrec->xinfo);
4608+
}
4609+
4610+
/*
4611+
* Utility function to call xact_redo_commit_internal for compact form of message.
4612+
*/
4613+
static void
4614+
xact_redo_commit_compact(xl_xact_commit_compact *xlrec,
4615+
TransactionId xid, XLogRecPtr lsn)
4616+
{
4617+
xact_redo_commit_internal(xid, lsn, xlrec->subxacts, xlrec->nsubxacts,
4618+
NULL, 0, /* inval msgs */
4619+
NULL, 0, /* relfilenodes */
4620+
InvalidOid, /* dbId */
4621+
InvalidOid, /* tsId */
4622+
0); /* xinfo */
45584623
}
45594624

45604625
/*
@@ -4655,7 +4720,13 @@ xact_redo(XLogRecPtr lsn, XLogRecord *record)
46554720
/* Backup blocks are not used in xact records */
46564721
Assert(!(record->xl_info & XLR_BKP_BLOCK_MASK));
46574722

4658-
if (info == XLOG_XACT_COMMIT)
4723+
if (info == XLOG_XACT_COMMIT_COMPACT)
4724+
{
4725+
xl_xact_commit_compact *xlrec = (xl_xact_commit_compact *) XLogRecGetData(record);
4726+
4727+
xact_redo_commit_compact(xlrec, record->xl_xid, lsn);
4728+
}
4729+
else if (info == XLOG_XACT_COMMIT)
46594730
{
46604731
xl_xact_commit *xlrec = (xl_xact_commit *) XLogRecGetData(record);
46614732

@@ -4703,9 +4774,9 @@ static void
47034774
xact_desc_commit(StringInfo buf, xl_xact_commit *xlrec)
47044775
{
47054776
int i;
4706-
TransactionId *xacts;
4777+
TransactionId *subxacts;
47074778

4708-
xacts = (TransactionId *) &xlrec->xnodes[xlrec->nrels];
4779+
subxacts = (TransactionId *) &xlrec->xnodes[xlrec->nrels];
47094780

47104781
appendStringInfoString(buf, timestamptz_to_str(xlrec->xact_time));
47114782

@@ -4724,15 +4795,15 @@ xact_desc_commit(StringInfo buf, xl_xact_commit *xlrec)
47244795
{
47254796
appendStringInfo(buf, "; subxacts:");
47264797
for (i = 0; i < xlrec->nsubxacts; i++)
4727-
appendStringInfo(buf, " %u", xacts[i]);
4798+
appendStringInfo(buf, " %u", subxacts[i]);
47284799
}
47294800
if (xlrec->nmsgs > 0)
47304801
{
47314802
SharedInvalidationMessage *msgs;
47324803

4733-
msgs = (SharedInvalidationMessage *) &xacts[xlrec->nsubxacts];
4804+
msgs = (SharedInvalidationMessage *) &subxacts[xlrec->nsubxacts];
47344805

4735-
if (XactCompletionRelcacheInitFileInval(xlrec))
4806+
if (XactCompletionRelcacheInitFileInval(xlrec->xinfo))
47364807
appendStringInfo(buf, "; relcache init file inval dbid %u tsid %u",
47374808
xlrec->dbId, xlrec->tsId);
47384809

@@ -4758,6 +4829,21 @@ xact_desc_commit(StringInfo buf, xl_xact_commit *xlrec)
47584829
}
47594830
}
47604831

4832+
static void
4833+
xact_desc_commit_compact(StringInfo buf, xl_xact_commit_compact *xlrec)
4834+
{
4835+
int i;
4836+
4837+
appendStringInfoString(buf, timestamptz_to_str(xlrec->xact_time));
4838+
4839+
if (xlrec->nsubxacts > 0)
4840+
{
4841+
appendStringInfo(buf, "; subxacts:");
4842+
for (i = 0; i < xlrec->nsubxacts; i++)
4843+
appendStringInfo(buf, " %u", xlrec->subxacts[i]);
4844+
}
4845+
}
4846+
47614847
static void
47624848
xact_desc_abort(StringInfo buf, xl_xact_abort *xlrec)
47634849
{
@@ -4802,7 +4888,14 @@ xact_desc(StringInfo buf, uint8 xl_info, char *rec)
48024888
{
48034889
uint8 info = xl_info & ~XLR_INFO_MASK;
48044890

4805-
if (info == XLOG_XACT_COMMIT)
4891+
if (info == XLOG_XACT_COMMIT_COMPACT)
4892+
{
4893+
xl_xact_commit_compact *xlrec = (xl_xact_commit_compact *) rec;
4894+
4895+
appendStringInfo(buf, "commit: ");
4896+
xact_desc_commit_compact(buf, xlrec);
4897+
}
4898+
else if (info == XLOG_XACT_COMMIT)
48064899
{
48074900
xl_xact_commit *xlrec = (xl_xact_commit *) rec;
48084901

src/backend/access/transam/xlog.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5593,7 +5593,14 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
55935593
if (record->xl_rmid != RM_XACT_ID && record->xl_rmid != RM_XLOG_ID)
55945594
return false;
55955595
record_info = record->xl_info & ~XLR_INFO_MASK;
5596-
if (record->xl_rmid == RM_XACT_ID && record_info == XLOG_XACT_COMMIT)
5596+
if (record->xl_rmid == RM_XACT_ID && record_info == XLOG_XACT_COMMIT_COMPACT)
5597+
{
5598+
xl_xact_commit_compact *recordXactCommitData;
5599+
5600+
recordXactCommitData = (xl_xact_commit_compact *) XLogRecGetData(record);
5601+
recordXtime = recordXactCommitData->xact_time;
5602+
}
5603+
else if (record->xl_rmid == RM_XACT_ID && record_info == XLOG_XACT_COMMIT)
55975604
{
55985605
xl_xact_commit *recordXactCommitData;
55995606

@@ -5680,7 +5687,7 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
56805687
recoveryStopTime = recordXtime;
56815688
recoveryStopAfter = *includeThis;
56825689

5683-
if (record_info == XLOG_XACT_COMMIT)
5690+
if (record_info == XLOG_XACT_COMMIT_COMPACT || record_info == XLOG_XACT_COMMIT)
56845691
{
56855692
if (recoveryStopAfter)
56865693
ereport(LOG,

0 commit comments

Comments
 (0)