]> granicus.if.org Git - postgresql/commitdiff
In checkpoint, move the check for in-progress xacts out of critical section.
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Fri, 4 Apr 2014 14:29:50 +0000 (17:29 +0300)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Fri, 4 Apr 2014 14:31:22 +0000 (17:31 +0300)
GetVirtualXIDsDelayingChkpt calls palloc, which isn't safe in a critical
section. I thought I covered this case with the exemption for the
checkpointer, but CreateCheckPoint is also called from the startup process.

src/backend/access/transam/xlog.c

index e2a14de7212df869302be3bffb42f3880a0abca9..3a48227ad930871a2e524300d160a378717ecbd5 100644 (file)
@@ -8076,6 +8076,42 @@ CreateCheckPoint(int flags)
 
        TRACE_POSTGRESQL_CHECKPOINT_START(flags);
 
+       /*
+        * Get the other info we need for the checkpoint record.
+        */
+       LWLockAcquire(XidGenLock, LW_SHARED);
+       checkPoint.nextXid = ShmemVariableCache->nextXid;
+       checkPoint.oldestXid = ShmemVariableCache->oldestXid;
+       checkPoint.oldestXidDB = ShmemVariableCache->oldestXidDB;
+       LWLockRelease(XidGenLock);
+
+       /* Increase XID epoch if we've wrapped around since last checkpoint */
+       checkPoint.nextXidEpoch = ControlFile->checkPointCopy.nextXidEpoch;
+       if (checkPoint.nextXid < ControlFile->checkPointCopy.nextXid)
+               checkPoint.nextXidEpoch++;
+
+       LWLockAcquire(OidGenLock, LW_SHARED);
+       checkPoint.nextOid = ShmemVariableCache->nextOid;
+       if (!shutdown)
+               checkPoint.nextOid += ShmemVariableCache->oidCount;
+       LWLockRelease(OidGenLock);
+
+       MultiXactGetCheckptMulti(shutdown,
+                                                        &checkPoint.nextMulti,
+                                                        &checkPoint.nextMultiOffset,
+                                                        &checkPoint.oldestMulti,
+                                                        &checkPoint.oldestMultiDB);
+
+       /*
+        * Having constructed the checkpoint record, ensure all shmem disk buffers
+        * and commit-log buffers are flushed to disk.
+        *
+        * This I/O could fail for various reasons.  If so, we will fail to
+        * complete the checkpoint, but there is no reason to force a system
+        * panic. Accordingly, exit critical section while doing it.
+        */
+       END_CRIT_SECTION();
+
        /*
         * In some cases there are groups of actions that must all occur on one
         * side or the other of a checkpoint record. Before flushing the
@@ -8116,42 +8152,6 @@ CreateCheckPoint(int flags)
        }
        pfree(vxids);
 
-       /*
-        * Get the other info we need for the checkpoint record.
-        */
-       LWLockAcquire(XidGenLock, LW_SHARED);
-       checkPoint.nextXid = ShmemVariableCache->nextXid;
-       checkPoint.oldestXid = ShmemVariableCache->oldestXid;
-       checkPoint.oldestXidDB = ShmemVariableCache->oldestXidDB;
-       LWLockRelease(XidGenLock);
-
-       /* Increase XID epoch if we've wrapped around since last checkpoint */
-       checkPoint.nextXidEpoch = ControlFile->checkPointCopy.nextXidEpoch;
-       if (checkPoint.nextXid < ControlFile->checkPointCopy.nextXid)
-               checkPoint.nextXidEpoch++;
-
-       LWLockAcquire(OidGenLock, LW_SHARED);
-       checkPoint.nextOid = ShmemVariableCache->nextOid;
-       if (!shutdown)
-               checkPoint.nextOid += ShmemVariableCache->oidCount;
-       LWLockRelease(OidGenLock);
-
-       MultiXactGetCheckptMulti(shutdown,
-                                                        &checkPoint.nextMulti,
-                                                        &checkPoint.nextMultiOffset,
-                                                        &checkPoint.oldestMulti,
-                                                        &checkPoint.oldestMultiDB);
-
-       /*
-        * Having constructed the checkpoint record, ensure all shmem disk buffers
-        * and commit-log buffers are flushed to disk.
-        *
-        * This I/O could fail for various reasons.  If so, we will fail to
-        * complete the checkpoint, but there is no reason to force a system
-        * panic. Accordingly, exit critical section while doing it.
-        */
-       END_CRIT_SECTION();
-
        CheckPointGuts(checkPoint.redo, flags);
 
        /*