@@ -119,11 +119,11 @@ typedef struct GlobalTransactionData
119
119
int pgprocno ; /* ID of associated dummy PGPROC */
120
120
BackendId dummyBackendId ; /* similar to backend id for backends */
121
121
TimestampTz prepared_at ; /* time of preparation */
122
- XLogRecPtr prepare_lsn ; /* XLOG offset of prepare record end */
123
- XLogRecPtr prepare_xlogptr ; /* XLOG offset of prepare record start
124
- * or NULL if twophase data moved to file
125
- * after checkpoint.
122
+ XLogRecPtr prepare_start_lsn ; /* XLOG offset of prepare record start
123
+ * or InvalidXLogRecPtr if twophase data
124
+ * moved to file after checkpoint.
126
125
*/
126
+ XLogRecPtr prepare_end_lsn ; /* XLOG offset of prepare record end */
127
127
Oid owner ; /* ID of user that executed the xact */
128
128
BackendId locking_backend ; /* backend currently working on the xact */
129
129
bool valid ; /* TRUE if PGPROC entry is in proc array */
@@ -405,9 +405,9 @@ MarkAsPreparing(TransactionId xid, const char *gid,
405
405
pgxact -> nxids = 0 ;
406
406
407
407
gxact -> prepared_at = prepared_at ;
408
- /* initialize LSN to 0 (start of WAL) */
409
- gxact -> prepare_lsn = 0 ;
410
- gxact -> prepare_xlogptr = 0 ;
408
+ /* initialize LSN to InvalidXLogRecPtr */
409
+ gxact -> prepare_start_lsn = InvalidXLogRecPtr ;
410
+ gxact -> prepare_end_lsn = InvalidXLogRecPtr ;
411
411
gxact -> owner = owner ;
412
412
gxact -> locking_backend = MyBackendId ;
413
413
gxact -> valid = false;
@@ -1035,13 +1035,13 @@ EndPrepare(GlobalTransaction gxact)
1035
1035
XLogBeginInsert ();
1036
1036
for (record = records .head ; record != NULL ; record = record -> next )
1037
1037
XLogRegisterData (record -> data , record -> len );
1038
- gxact -> prepare_lsn = XLogInsert (RM_XACT_ID , XLOG_XACT_PREPARE );
1039
- XLogFlush (gxact -> prepare_lsn );
1038
+ gxact -> prepare_end_lsn = XLogInsert (RM_XACT_ID , XLOG_XACT_PREPARE );
1039
+ XLogFlush (gxact -> prepare_end_lsn );
1040
1040
1041
1041
/* If we crash now, we have prepared: WAL replay will fix things */
1042
1042
1043
1043
/* Store record's start location to read that later on Commit */
1044
- gxact -> prepare_xlogptr = ProcLastRecPtr ;
1044
+ gxact -> prepare_start_lsn = ProcLastRecPtr ;
1045
1045
1046
1046
/*
1047
1047
* Mark the prepared transaction as valid. As soon as xact.c marks
@@ -1079,7 +1079,7 @@ EndPrepare(GlobalTransaction gxact)
1079
1079
* Note that at this stage we have marked the prepare, but still show as
1080
1080
* running in the procarray (twice!) and continue to hold locks.
1081
1081
*/
1082
- SyncRepWaitForLSN (gxact -> prepare_lsn );
1082
+ SyncRepWaitForLSN (gxact -> prepare_end_lsn );
1083
1083
1084
1084
records .tail = records .head = NULL ;
1085
1085
records .num_chunks = 0 ;
@@ -1301,12 +1301,12 @@ FinishPreparedTransaction(const char *gid, bool isCommit)
1301
1301
/*
1302
1302
* Read and validate 2PC state data.
1303
1303
* State data can be stored in xlog or in files after xlog checkpoint.
1304
- * While checkpointing we set gxact->prepare_lsn to NULL to signalize
1304
+ * While checkpointing we set gxact->prepare_start_lsn to NULL to signalize
1305
1305
* that 2PC data is moved to files.
1306
1306
*/
1307
- if (gxact -> prepare_lsn )
1307
+ if (gxact -> prepare_start_lsn )
1308
1308
{
1309
- XlogReadTwoPhaseData (gxact -> prepare_xlogptr , & buf , NULL );
1309
+ XlogReadTwoPhaseData (gxact -> prepare_start_lsn , & buf , NULL );
1310
1310
}
1311
1311
else
1312
1312
{
@@ -1556,8 +1556,6 @@ CheckPointTwoPhase(XLogRecPtr redo_horizon)
1556
1556
int len ;
1557
1557
char * buf ;
1558
1558
1559
- fprintf (stderr , "=== Checkpoint: redo_horizon=%lX\n" , redo_horizon );
1560
-
1561
1559
if (max_prepared_xacts <= 0 )
1562
1560
return ; /* nothing to do */
1563
1561
@@ -1577,10 +1575,11 @@ CheckPointTwoPhase(XLogRecPtr redo_horizon)
1577
1575
GlobalTransaction gxact = TwoPhaseState -> prepXacts [i ];
1578
1576
PGXACT * pgxact = & ProcGlobal -> allPgXact [gxact -> pgprocno ];
1579
1577
1580
- if (gxact -> valid && gxact -> prepare_lsn && gxact -> prepare_lsn <= redo_horizon ){
1581
- XlogReadTwoPhaseData (gxact -> prepare_xlogptr , & buf , & len );
1578
+ if (gxact -> valid && gxact -> prepare_start_lsn != InvalidXLogRecPtr &&
1579
+ gxact -> prepare_end_lsn <= redo_horizon ){
1580
+ XlogReadTwoPhaseData (gxact -> prepare_start_lsn , & buf , & len );
1582
1581
RecreateTwoPhaseFile (pgxact -> xid , buf , len );
1583
- gxact -> prepare_lsn = ( XLogRecPtr ) NULL ;
1582
+ gxact -> prepare_start_lsn = InvalidXLogRecPtr ;
1584
1583
pfree (buf );
1585
1584
}
1586
1585
}
@@ -1916,12 +1915,8 @@ RecoverPreparedTransactions(void)
1916
1915
/*
1917
1916
* Recreate its GXACT and dummy PGPROC
1918
1917
*
1919
- * Note: since we don't have the PREPARE record's WAL location at
1920
- * hand, we leave prepare_lsn zeroes. This means the GXACT will
1921
- * be fsync'd on every future checkpoint. We assume this
1922
- * situation is infrequent enough that the performance cost is
1923
- * negligible (especially since we know the state file has already
1924
- * been fsynced).
1918
+ * MarkAsPreparing sets prepare_start_lsn to InvalidXLogRecPtr
1919
+ * so next checkpoint will skip that transaction.
1925
1920
*/
1926
1921
gxact = MarkAsPreparing (xid , hdr -> gid ,
1927
1922
hdr -> prepared_at ,
0 commit comments