]> granicus.if.org Git - postgresql/commitdiff
Allow transactions that don't write WAL to commit asynchronously.
authorRobert Haas <rhaas@postgresql.org>
Mon, 20 Dec 2010 17:59:33 +0000 (12:59 -0500)
committerRobert Haas <rhaas@postgresql.org>
Mon, 20 Dec 2010 17:59:33 +0000 (12:59 -0500)
This case can arise if a transaction has written data, but only to
temporary tables.  Loss of the commit record in case of a crash won't
matter, because the temporary tables will be lost anyway.

Reviewed by Heikki Linnakangas and Simon Riggs.

src/backend/access/transam/xact.c

index 79c9c0d844618f2a3c03eac48a714fbe2d00f021..67f817ca4b8e401d8ef02fac3df4f41fea485a18 100644 (file)
@@ -907,6 +907,7 @@ RecordTransactionCommit(void)
        int                     nmsgs = 0;
        SharedInvalidationMessage *invalMessages = NULL;
        bool            RelcacheInitFileInval = false;
+       bool            wrote_xlog;
 
        /* Get data needed for commit record */
        nrels = smgrGetPendingDeletes(true, &rels);
@@ -914,6 +915,7 @@ RecordTransactionCommit(void)
        if (XLogStandbyInfoActive())
                nmsgs = xactGetCommittedInvalidationMessages(&invalMessages,
                                                                                                         &RelcacheInitFileInval);
+       wrote_xlog = (XactLastRecEnd.xrecoff != 0);
 
        /*
         * If we haven't been assigned an XID yet, we neither can, nor do we want
@@ -940,7 +942,7 @@ RecordTransactionCommit(void)
                 * assigned is a sequence advance record due to nextval() --- we want
                 * to flush that to disk before reporting commit.)
                 */
-               if (XactLastRecEnd.xrecoff == 0)
+               if (!wrote_xlog)
                        goto cleanup;
        }
        else
@@ -1028,16 +1030,27 @@ RecordTransactionCommit(void)
        }
 
        /*
-        * Check if we want to commit asynchronously.  If the user has set
-        * synchronous_commit = off, and we're not doing cleanup of any non-temp
-        * rels nor committing any command that wanted to force sync commit, then
-        * we can defer flushing XLOG.  (We must not allow asynchronous commit if
-        * there are any non-temp tables to be deleted, because we might delete
-        * the files before the COMMIT record is flushed to disk.  We do allow
-        * asynchronous commit if all to-be-deleted tables are temporary though,
-        * since they are lost anyway if we crash.)
+        * Check if we want to commit asynchronously.  We can allow the XLOG flush
+        * to happen asynchronously if synchronous_commit=off, or if the current
+        * transaction has not performed any WAL-logged operation.  The latter case
+        * can arise if the current transaction wrote only to temporary tables.
+        * In case of a crash, the loss of such a transaction will be irrelevant
+        * since temp tables will be lost anyway.  (Given the foregoing, you might
+        * think that it would be unnecessary to emit the XLOG record at all in
+        * this case, but we don't currently try to do that.  It would certainly
+        * cause problems at least in Hot Standby mode, where the KnownAssignedXids
+        * machinery requires tracking every XID assignment.  It might be OK to
+        * skip it only when wal_level < hot_standby, but for now we don't.)
+        *
+        * However, if we're doing cleanup of any non-temp rels or committing any
+        * command that wanted to force sync commit, then we must flush XLOG
+        * immediately.  (We must not allow asynchronous commit if there are any
+        * non-temp tables to be deleted, because we might delete the files before
+        * the COMMIT record is flushed to disk.  We do allow asynchronous commit
+        * if all to-be-deleted tables are temporary though, since they are lost
+        * anyway if we crash.)
         */
-       if (XactSyncCommit || forceSyncCommit || nrels > 0)
+       if ((wrote_xlog && XactSyncCommit) || forceSyncCommit || nrels > 0)
        {
                /*
                 * Synchronous commit case: