@@ -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 */
970966BufmgrCommit ();
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)
1002986MyProc -> inCommit = true;
1003987
1004988SetCurrentTransactionStopTimestamp ();
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 */
44434472static 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 ;
44484480TransactionId max_xid ;
44494481int 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}
44814508else
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 );
45314558ForkNumber fork ;
45324559
45334560for (fork = 0 ;fork <=MAX_FORKNUM ;fork ++ )
45344561{
45354562if (smgrexists (srel ,fork ))
45364563{
4537- XLogDropRelation (xlrec -> xnodes [i ],fork );
4564+ XLogDropRelation (xnodes [i ],fork );
45384565smgrdounlink (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 ))
45574584XLogFlush (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 */
46564721Assert (!(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{
46604731xl_xact_commit * xlrec = (xl_xact_commit * )XLogRecGetData (record );
46614732
@@ -4703,9 +4774,9 @@ static void
47034774xact_desc_commit (StringInfo buf ,xl_xact_commit * xlrec )
47044775{
47054776int i ;
4706- TransactionId * xacts ;
4777+ TransactionId * subxacts ;
47074778
4708- xacts = (TransactionId * )& xlrec -> xnodes [xlrec -> nrels ];
4779+ subxacts = (TransactionId * )& xlrec -> xnodes [xlrec -> nrels ];
47094780
47104781appendStringInfoString (buf ,timestamptz_to_str (xlrec -> xact_time ));
47114782
@@ -4724,15 +4795,15 @@ xact_desc_commit(StringInfo buf, xl_xact_commit *xlrec)
47244795{
47254796appendStringInfo (buf ,"; subxacts:" );
47264797for (i = 0 ;i < xlrec -> nsubxacts ;i ++ )
4727- appendStringInfo (buf ," %u" ,xacts [i ]);
4798+ appendStringInfo (buf ," %u" ,subxacts [i ]);
47284799}
47294800if (xlrec -> nmsgs > 0 )
47304801{
47314802SharedInvalidationMessage * msgs ;
47324803
4733- msgs = (SharedInvalidationMessage * )& xacts [xlrec -> nsubxacts ];
4804+ msgs = (SharedInvalidationMessage * )& subxacts [xlrec -> nsubxacts ];
47344805
4735- if (XactCompletionRelcacheInitFileInval (xlrec ))
4806+ if (XactCompletionRelcacheInitFileInval (xlrec -> xinfo ))
47364807appendStringInfo (buf ,"; relcache init file inval dbid %u tsid %u" ,
47374808xlrec -> 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+
47614847static void
47624848xact_desc_abort (StringInfo buf ,xl_xact_abort * xlrec )
47634849{
@@ -4802,7 +4888,14 @@ xact_desc(StringInfo buf, uint8 xl_info, char *rec)
48024888{
48034889uint8 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{
48074900xl_xact_commit * xlrec = (xl_xact_commit * )rec ;
48084901