@@ -119,11 +119,11 @@ typedef struct GlobalTransactionData
119119 int pgprocno ; /* ID of associated dummy PGPROC */
120120 BackendId dummyBackendId ; /* similar to backend id for backends */
121121 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.
126125 */
126+ XLogRecPtr prepare_end_lsn ; /* XLOG offset of prepare record end */
127127 Oid owner ; /* ID of user that executed the xact */
128128 BackendId locking_backend ; /* backend currently working on the xact */
129129 bool valid ; /* TRUE if PGPROC entry is in proc array */
@@ -405,9 +405,9 @@ MarkAsPreparing(TransactionId xid, const char *gid,
405405 pgxact -> nxids = 0 ;
406406
407407 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 ;
411411 gxact -> owner = owner ;
412412 gxact -> locking_backend = MyBackendId ;
413413 gxact -> valid = false;
@@ -1035,13 +1035,13 @@ EndPrepare(GlobalTransaction gxact)
10351035 XLogBeginInsert ();
10361036 for (record = records .head ; record != NULL ; record = record -> next )
10371037 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 );
10401040
10411041 /* If we crash now, we have prepared: WAL replay will fix things */
10421042
10431043 /* Store record's start location to read that later on Commit */
1044- gxact -> prepare_xlogptr = ProcLastRecPtr ;
1044+ gxact -> prepare_start_lsn = ProcLastRecPtr ;
10451045
10461046 /*
10471047 * Mark the prepared transaction as valid. As soon as xact.c marks
@@ -1079,7 +1079,7 @@ EndPrepare(GlobalTransaction gxact)
10791079 * Note that at this stage we have marked the prepare, but still show as
10801080 * running in the procarray (twice!) and continue to hold locks.
10811081 */
1082- SyncRepWaitForLSN (gxact -> prepare_lsn );
1082+ SyncRepWaitForLSN (gxact -> prepare_end_lsn );
10831083
10841084 records .tail = records .head = NULL ;
10851085 records .num_chunks = 0 ;
@@ -1301,12 +1301,12 @@ FinishPreparedTransaction(const char *gid, bool isCommit)
13011301 /*
13021302 * Read and validate 2PC state data.
13031303 * 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
13051305 * that 2PC data is moved to files.
13061306 */
1307- if (gxact -> prepare_lsn )
1307+ if (gxact -> prepare_start_lsn )
13081308 {
1309- XlogReadTwoPhaseData (gxact -> prepare_xlogptr , & buf , NULL );
1309+ XlogReadTwoPhaseData (gxact -> prepare_start_lsn , & buf , NULL );
13101310 }
13111311 else
13121312 {
@@ -1556,8 +1556,6 @@ CheckPointTwoPhase(XLogRecPtr redo_horizon)
15561556 int len ;
15571557 char * buf ;
15581558
1559- fprintf (stderr , "=== Checkpoint: redo_horizon=%lX\n" , redo_horizon );
1560-
15611559 if (max_prepared_xacts <= 0 )
15621560 return ; /* nothing to do */
15631561
@@ -1577,10 +1575,11 @@ CheckPointTwoPhase(XLogRecPtr redo_horizon)
15771575 GlobalTransaction gxact = TwoPhaseState -> prepXacts [i ];
15781576 PGXACT * pgxact = & ProcGlobal -> allPgXact [gxact -> pgprocno ];
15791577
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 );
15821581 RecreateTwoPhaseFile (pgxact -> xid , buf , len );
1583- gxact -> prepare_lsn = ( XLogRecPtr ) NULL ;
1582+ gxact -> prepare_start_lsn = InvalidXLogRecPtr ;
15841583 pfree (buf );
15851584 }
15861585 }
@@ -1916,12 +1915,8 @@ RecoverPreparedTransactions(void)
19161915 /*
19171916 * Recreate its GXACT and dummy PGPROC
19181917 *
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.
19251920 */
19261921 gxact = MarkAsPreparing (xid , hdr -> gid ,
19271922 hdr -> prepared_at ,
0 commit comments