@@ -962,25 +962,9 @@ RecordTransactionCommit(void)
962
962
/*
963
963
* Begin commit critical section and insert the commit XLOG record.
964
964
*/
965
- XLogRecData rdata [4 ];
966
- int lastrdata = 0 ;
967
- xl_xact_commit xlrec ;
968
-
969
965
/* Tell bufmgr and smgr to prepare for commit */
970
966
BufmgrCommit ();
971
967
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
-
984
968
/*
985
969
* Mark ourselves as within our "commit critical section". This
986
970
* forces any concurrent checkpoint to wait until we've updated
@@ -1002,43 +986,88 @@ RecordTransactionCommit(void)
1002
986
MyProc -> inCommit = true;
1003
987
1004
988
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 )
1023
994
{
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 );
1029
1047
}
1030
- /* dump shared cache invalidation messages */
1031
- if (nmsgs > 0 )
1048
+ else
1032
1049
{
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 ;
1040
1068
1041
- (void ) XLogInsert (RM_XACT_ID , XLOG_XACT_COMMIT , rdata );
1069
+ (void ) XLogInsert (RM_XACT_ID , XLOG_XACT_COMMIT_COMPACT , rdata );
1070
+ }
1042
1071
}
1043
1072
1044
1073
/*
@@ -4441,19 +4470,17 @@ xactGetCommittedChildren(TransactionId **ptr)
4441
4470
* actions for which the order of execution is critical.
4442
4471
*/
4443
4472
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 )
4445
4479
{
4446
- TransactionId * sub_xids ;
4447
- SharedInvalidationMessage * inval_msgs ;
4448
4480
TransactionId max_xid ;
4449
4481
int i ;
4450
4482
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 );
4457
4484
4458
4485
/*
4459
4486
* 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)
4476
4503
/*
4477
4504
* Mark the transaction committed in pg_clog.
4478
4505
*/
4479
- TransactionIdCommitTree (xid , xlrec -> nsubxacts , sub_xids );
4506
+ TransactionIdCommitTree (xid , nsubxacts , sub_xids );
4480
4507
}
4481
4508
else
4482
4509
{
@@ -4500,41 +4527,41 @@ xact_redo_commit(xl_xact_commit *xlrec, TransactionId xid, XLogRecPtr lsn)
4500
4527
* bits set on changes made by transactions that haven't yet
4501
4528
* recovered. It's unlikely but it's good to be safe.
4502
4529
*/
4503
- TransactionIdAsyncCommitTree (xid , xlrec -> nsubxacts , sub_xids , lsn );
4530
+ TransactionIdAsyncCommitTree (xid , nsubxacts , sub_xids , lsn );
4504
4531
4505
4532
/*
4506
4533
* We must mark clog before we update the ProcArray.
4507
4534
*/
4508
- ExpireTreeKnownAssignedTransactionIds (xid , xlrec -> nsubxacts , sub_xids , max_xid );
4535
+ ExpireTreeKnownAssignedTransactionIds (xid , nsubxacts , sub_xids , max_xid );
4509
4536
4510
4537
/*
4511
4538
* Send any cache invalidations attached to the commit. We must
4512
4539
* maintain the same order of invalidation then release locks as
4513
4540
* occurs in CommitTransaction().
4514
4541
*/
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 );
4518
4545
4519
4546
/*
4520
4547
* Release locks, if any. We do this for both two phase and normal one
4521
4548
* phase transactions. In effect we are ignoring the prepare phase and
4522
4549
* just going straight to lock release.
4523
4550
*/
4524
- StandbyReleaseLockTree (xid , xlrec -> nsubxacts , sub_xids );
4551
+ StandbyReleaseLockTree (xid , nsubxacts , sub_xids );
4525
4552
}
4526
4553
4527
4554
/* Make sure files supposed to be dropped are dropped */
4528
- for (i = 0 ; i < xlrec -> nrels ; i ++ )
4555
+ for (i = 0 ; i < nrels ; i ++ )
4529
4556
{
4530
- SMgrRelation srel = smgropen (xlrec -> xnodes [i ], InvalidBackendId );
4557
+ SMgrRelation srel = smgropen (xnodes [i ], InvalidBackendId );
4531
4558
ForkNumber fork ;
4532
4559
4533
4560
for (fork = 0 ; fork <= MAX_FORKNUM ; fork ++ )
4534
4561
{
4535
4562
if (smgrexists (srel , fork ))
4536
4563
{
4537
- XLogDropRelation (xlrec -> xnodes [i ], fork );
4564
+ XLogDropRelation (xnodes [i ], fork );
4538
4565
smgrdounlink (srel , fork , true);
4539
4566
}
4540
4567
}
@@ -4553,8 +4580,46 @@ xact_redo_commit(xl_xact_commit *xlrec, TransactionId xid, XLogRecPtr lsn)
4553
4580
* to reduce that problem window, for any user that requested
4554
4581
* ForceSyncCommit().
4555
4582
*/
4556
- if (XactCompletionForceSyncCommit (xlrec ))
4583
+ if (XactCompletionForceSyncCommit (xinfo ))
4557
4584
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 */
4558
4623
}
4559
4624
4560
4625
/*
@@ -4655,7 +4720,13 @@ xact_redo(XLogRecPtr lsn, XLogRecord *record)
4655
4720
/* Backup blocks are not used in xact records */
4656
4721
Assert (!(record -> xl_info & XLR_BKP_BLOCK_MASK ));
4657
4722
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 )
4659
4730
{
4660
4731
xl_xact_commit * xlrec = (xl_xact_commit * ) XLogRecGetData (record );
4661
4732
@@ -4703,9 +4774,9 @@ static void
4703
4774
xact_desc_commit (StringInfo buf , xl_xact_commit * xlrec )
4704
4775
{
4705
4776
int i ;
4706
- TransactionId * xacts ;
4777
+ TransactionId * subxacts ;
4707
4778
4708
- xacts = (TransactionId * ) & xlrec -> xnodes [xlrec -> nrels ];
4779
+ subxacts = (TransactionId * ) & xlrec -> xnodes [xlrec -> nrels ];
4709
4780
4710
4781
appendStringInfoString (buf , timestamptz_to_str (xlrec -> xact_time ));
4711
4782
@@ -4724,15 +4795,15 @@ xact_desc_commit(StringInfo buf, xl_xact_commit *xlrec)
4724
4795
{
4725
4796
appendStringInfo (buf , "; subxacts:" );
4726
4797
for (i = 0 ; i < xlrec -> nsubxacts ; i ++ )
4727
- appendStringInfo (buf , " %u" , xacts [i ]);
4798
+ appendStringInfo (buf , " %u" , subxacts [i ]);
4728
4799
}
4729
4800
if (xlrec -> nmsgs > 0 )
4730
4801
{
4731
4802
SharedInvalidationMessage * msgs ;
4732
4803
4733
- msgs = (SharedInvalidationMessage * ) & xacts [xlrec -> nsubxacts ];
4804
+ msgs = (SharedInvalidationMessage * ) & subxacts [xlrec -> nsubxacts ];
4734
4805
4735
- if (XactCompletionRelcacheInitFileInval (xlrec ))
4806
+ if (XactCompletionRelcacheInitFileInval (xlrec -> xinfo ))
4736
4807
appendStringInfo (buf , "; relcache init file inval dbid %u tsid %u" ,
4737
4808
xlrec -> dbId , xlrec -> tsId );
4738
4809
@@ -4758,6 +4829,21 @@ xact_desc_commit(StringInfo buf, xl_xact_commit *xlrec)
4758
4829
}
4759
4830
}
4760
4831
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
+
4761
4847
static void
4762
4848
xact_desc_abort (StringInfo buf , xl_xact_abort * xlrec )
4763
4849
{
@@ -4802,7 +4888,14 @@ xact_desc(StringInfo buf, uint8 xl_info, char *rec)
4802
4888
{
4803
4889
uint8 info = xl_info & ~XLR_INFO_MASK ;
4804
4890
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 )
4806
4899
{
4807
4900
xl_xact_commit * xlrec = (xl_xact_commit * ) rec ;
4808
4901
0 commit comments