Rearrange storage of data in xl_running_xacts.
authorSimon Riggs <simon@2ndQuadrant.com>
Sun, 2 Dec 2012 19:39:37 +0000 (19:39 +0000)
committerSimon Riggs <simon@2ndQuadrant.com>
Sun, 2 Dec 2012 19:39:37 +0000 (19:39 +0000)
Previously we stored all xids mixed together.
Now we store top-level xids first, followed
by all subxids. Also skip logging any subxids
if the snapshot is suboverflowed, since there
are potentially large numbers of them and they
are not useful in that case anyway. Has value
in the envisaged design for decoding of WAL.
No planned effect on Hot Standby.

Andres Freund, reviewed by me

src/backend/access/transam/xlog.c
src/backend/storage/ipc/procarray.c
src/backend/storage/ipc/standby.c
src/include/storage/standby.h

index f78a0882debc6297af2417496271eccd555ab1d5..f090baed4f18719e2f808ac7ca5b3a86a6aad175 100644 (file)
@@ -5631,6 +5631,7 @@ StartupXLOG(void)
                 * subxids are listed with their parent prepared transactions.
                 */
                running.xcnt = nxids;
+               running.subxcnt = 0;
                running.subxid_overflow = false;
                running.nextXid = checkPoint.nextXid;
                running.oldestRunningXid = oldestActiveXID;
@@ -7834,6 +7835,7 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record)
             * with their parent prepared transactions.
             */
            running.xcnt = nxids;
+           running.subxcnt = 0;
            running.subxid_overflow = false;
            running.nextXid = checkPoint.nextXid;
            running.oldestRunningXid = oldestActiveXID;
index 8c0d7b0ea957744edde57568e70d80cf34856a01..a98358daf53c0bd398944b4ac205f96e8b807c39 100644 (file)
@@ -501,6 +501,13 @@ ProcArrayApplyRecoveryInfo(RunningTransactions running)
     * Remove stale transactions, if any.
     */
    ExpireOldKnownAssignedTransactionIds(running->oldestRunningXid);
+
+   /*
+    * Remove stale locks, if any.
+    *
+    * Locks are always assigned to the toplevel xid so we don't need to care
+    * about subxcnt/subxids (and by extension not about ->suboverflowed).
+    */
    StandbyReleaseOldLocks(running->xcnt, running->xids);
 
    /*
@@ -581,13 +588,13 @@ ProcArrayApplyRecoveryInfo(RunningTransactions running)
     * Allocate a temporary array to avoid modifying the array passed as
     * argument.
     */
-   xids = palloc(sizeof(TransactionId) * running->xcnt);
+   xids = palloc(sizeof(TransactionId) * (running->xcnt + running->subxcnt));
 
    /*
     * Add to the temp array any xids which have not already completed.
     */
    nxids = 0;
-   for (i = 0; i < running->xcnt; i++)
+   for (i = 0; i < running->xcnt + running->subxcnt; i++)
    {
        TransactionId xid = running->xids[i];
 
@@ -1627,15 +1634,13 @@ GetRunningTransactionData(void)
    oldestRunningXid = ShmemVariableCache->nextXid;
 
    /*
-    * Spin over procArray collecting all xids and subxids.
+    * Spin over procArray collecting all xids
     */
    for (index = 0; index < arrayP->numProcs; index++)
    {
        int         pgprocno = arrayP->pgprocnos[index];
-       volatile PGPROC *proc = &allProcs[pgprocno];
        volatile PGXACT *pgxact = &allPgXact[pgprocno];
        TransactionId xid;
-       int         nxids;
 
        /* Fetch xid just once - see GetNewTransactionId */
        xid = pgxact->xid;
@@ -1652,30 +1657,46 @@ GetRunningTransactionData(void)
        if (TransactionIdPrecedes(xid, oldestRunningXid))
            oldestRunningXid = xid;
 
-       /*
-        * Save subtransaction XIDs. Other backends can't add or remove
-        * entries while we're holding XidGenLock.
-        */
-       nxids = pgxact->nxids;
-       if (nxids > 0)
-       {
-           memcpy(&xids[count], (void *) proc->subxids.xids,
-                  nxids * sizeof(TransactionId));
-           count += nxids;
-           subcount += nxids;
+       if (pgxact->overflowed)
+           suboverflowed = true;
+   }
 
-           if (pgxact->overflowed)
-               suboverflowed = true;
+   /*
+    * Spin over procArray collecting all subxids, but only if there hasn't
+    * been a suboverflow.
+    */
+   if (!suboverflowed)
+   {
+       for (index = 0; index < arrayP->numProcs; index++)
+       {
+           int         pgprocno = arrayP->pgprocnos[index];
+           volatile PGPROC *proc = &allProcs[pgprocno];
+           volatile PGXACT *pgxact = &allPgXact[pgprocno];
+           int         nxids;
 
            /*
-            * Top-level XID of a transaction is always less than any of its
-            * subxids, so we don't need to check if any of the subxids are
-            * smaller than oldestRunningXid
+            * Save subtransaction XIDs. Other backends can't add or remove
+            * entries while we're holding XidGenLock.
             */
+           nxids = pgxact->nxids;
+           if (nxids > 0)
+           {
+               memcpy(&xids[count], (void *) proc->subxids.xids,
+                      nxids * sizeof(TransactionId));
+               count += nxids;
+               subcount += nxids;
+
+               /*
+                * Top-level XID of a transaction is always less than any of
+                * its subxids, so we don't need to check if any of the subxids
+                * are smaller than oldestRunningXid
+                */
+           }
        }
    }
 
-   CurrentRunningXacts->xcnt = count;
+   CurrentRunningXacts->xcnt = count - subcount;
+   CurrentRunningXacts->subxcnt = subcount;
    CurrentRunningXacts->subxid_overflow = suboverflowed;
    CurrentRunningXacts->nextXid = ShmemVariableCache->nextXid;
    CurrentRunningXacts->oldestRunningXid = oldestRunningXid;
index 7fd94f3e50a26c9380c14a4964852c12e2089335..35548d1d1fbf3c9bb7e48d96adf9896e2de9cb4a 100644 (file)
@@ -778,6 +778,7 @@ standby_redo(XLogRecPtr lsn, XLogRecord *record)
        RunningTransactionsData running;
 
        running.xcnt = xlrec->xcnt;
+       running.subxcnt = xlrec->subxcnt;
        running.subxid_overflow = xlrec->subxid_overflow;
        running.nextXid = xlrec->nextXid;
        running.latestCompletedXid = xlrec->latestCompletedXid;
@@ -897,6 +898,7 @@ LogCurrentRunningXacts(RunningTransactions CurrRunningXacts)
    XLogRecPtr  recptr;
 
    xlrec.xcnt = CurrRunningXacts->xcnt;
+   xlrec.subxcnt = CurrRunningXacts->subxcnt;
    xlrec.subxid_overflow = CurrRunningXacts->subxid_overflow;
    xlrec.nextXid = CurrRunningXacts->nextXid;
    xlrec.oldestRunningXid = CurrRunningXacts->oldestRunningXid;
@@ -912,7 +914,7 @@ LogCurrentRunningXacts(RunningTransactions CurrRunningXacts)
    {
        rdata[0].next = &(rdata[1]);
        rdata[1].data = (char *) CurrRunningXacts->xids;
-       rdata[1].len = xlrec.xcnt * sizeof(TransactionId);
+       rdata[1].len = (xlrec.xcnt + xlrec.subxcnt) * sizeof(TransactionId);
        rdata[1].buffer = InvalidBuffer;
        lastrdata = 1;
    }
@@ -931,8 +933,8 @@ LogCurrentRunningXacts(RunningTransactions CurrRunningXacts)
             CurrRunningXacts->nextXid);
    else
        elog(trace_recovery(DEBUG2),
-            "snapshot of %u running transaction ids (lsn %X/%X oldest xid %u latest complete %u next xid %u)",
-            CurrRunningXacts->xcnt,
+            "snapshot of %u+%u running transaction ids (lsn %X/%X oldest xid %u latest complete %u next xid %u)",
+            CurrRunningXacts->xcnt, CurrRunningXacts->subxcnt,
             (uint32) (recptr >> 32), (uint32) recptr,
             CurrRunningXacts->oldestRunningXid,
             CurrRunningXacts->latestCompletedXid,
index 7024fc4f3c2d2d105ab6d5898b5e362a59937148..f917b89f7e120ea8e4d7b10be91af8c78fc7df4f 100644 (file)
@@ -68,6 +68,7 @@ typedef struct xl_standby_locks
 typedef struct xl_running_xacts
 {
    int         xcnt;           /* # of xact ids in xids[] */
+   int         subxcnt;            /* # of subxact ids in xids[] */
    bool        subxid_overflow;    /* snapshot overflowed, subxids missing */
    TransactionId nextXid;      /* copy of ShmemVariableCache->nextXid */
    TransactionId oldestRunningXid;     /* *not* oldestXmin */
@@ -98,6 +99,7 @@ extern void standby_desc(StringInfo buf, uint8 xl_info, char *rec);
 typedef struct RunningTransactionsData
 {
    int         xcnt;           /* # of xact ids in xids[] */
+   int         subxcnt;            /* # of subxact ids in xids[] */
    bool        subxid_overflow;    /* snapshot overflowed, subxids missing */
    TransactionId nextXid;      /* copy of ShmemVariableCache->nextXid */
    TransactionId oldestRunningXid;     /* *not* oldestXmin */