]> granicus.if.org Git - postgresql/commitdiff
Improve the performance of relation deletes during recovery.
authorFujii Masao <fujii@postgresql.org>
Wed, 4 Jul 2018 17:21:15 +0000 (02:21 +0900)
committerFujii Masao <fujii@postgresql.org>
Wed, 4 Jul 2018 17:27:05 +0000 (02:27 +0900)
When multiple relations are deleted at the same transaction,
the files of those relations are deleted by one call to smgrdounlinkall(),
which leads to scan whole shared_buffers only one time. OTOH,
previously, during recovery, smgrdounlink() (not smgrdounlinkall()) was
called for each file to delete, which led to scan shared_buffers
multiple times. Obviously this could cause to increase the WAL replay
time very much especially when shared_buffers was huge.

To alleviate this situation, this commit changes the recovery so that
it also calls smgrdounlinkall() only one time to delete multiple
relation files.

This is just fix for oversight of commit 279628a0a7, not new feature.
So, per discussion on pgsql-hackers, we concluded to backpatch this
to all supported versions.

Author: Fujii Masao
Reviewed-by: Michael Paquier, Andres Freund, Thomas Munro, Kyotaro Horiguchi, Takayuki Tsunakawa
Discussion: https://postgr.es/m/CAHGQGwHVQkdfDqtvGVkty+19cQakAydXn1etGND3X0PHbZ3+6w@mail.gmail.com

src/backend/access/transam/twophase.c
src/backend/access/transam/xact.c
src/backend/storage/smgr/md.c
src/include/storage/smgr.h

index c7cde25f835ca62fd43f77b892c6ac7e5991338d..a23eed568318f391e46b100d3579eccc412fe00e 100644 (file)
@@ -1346,7 +1346,6 @@ FinishPreparedTransaction(const char *gid, bool isCommit)
        RelFileNode *delrels;
        int                     ndelrels;
        SharedInvalidationMessage *invalmsgs;
-       int                     i;
 
        /*
         * Validate the GID, and lock the GXACT to ensure that two backends do not
@@ -1438,13 +1437,9 @@ FinishPreparedTransaction(const char *gid, bool isCommit)
                delrels = abortrels;
                ndelrels = hdr->nabortrels;
        }
-       for (i = 0; i < ndelrels; i++)
-       {
-               SMgrRelation srel = smgropen(delrels[i], InvalidBackendId);
 
-               smgrdounlink(srel, false);
-               smgrclose(srel);
-       }
+       /* Make sure files supposed to be dropped are dropped */
+       DropRelationFiles(delrels, ndelrels, false);
 
        /*
         * Handle cache invalidation messages.
index 150a0e8914068ad04e6874887c320e9de234b268..225775ceb4aae1e2947ee94d347599470a8a9a4d 100644 (file)
@@ -5349,7 +5349,6 @@ xact_redo_commit(xl_xact_parsed_commit *parsed,
                                 RepOriginId origin_id)
 {
        TransactionId max_xid;
-       int                     i;
        TimestampTz commit_time;
 
        max_xid = TransactionIdLatest(xid, parsed->nsubxacts, parsed->subxacts);
@@ -5467,16 +5466,8 @@ xact_redo_commit(xl_xact_parsed_commit *parsed,
                 */
                XLogFlush(lsn);
 
-               for (i = 0; i < parsed->nrels; i++)
-               {
-                       SMgrRelation srel = smgropen(parsed->xnodes[i], InvalidBackendId);
-                       ForkNumber      fork;
-
-                       for (fork = 0; fork <= MAX_FORKNUM; fork++)
-                               XLogDropRelation(parsed->xnodes[i], fork);
-                       smgrdounlink(srel, true);
-                       smgrclose(srel);
-               }
+               /* Make sure files supposed to be dropped are dropped */
+               DropRelationFiles(parsed->xnodes, parsed->nrels, true);
        }
 
        /*
@@ -5515,7 +5506,6 @@ xact_redo_commit(xl_xact_parsed_commit *parsed,
 static void
 xact_redo_abort(xl_xact_parsed_abort *parsed, TransactionId xid)
 {
-       int                     i;
        TransactionId max_xid;
 
        /*
@@ -5577,16 +5567,7 @@ xact_redo_abort(xl_xact_parsed_abort *parsed, TransactionId xid)
        }
 
        /* Make sure files supposed to be dropped are dropped */
-       for (i = 0; i < parsed->nrels; i++)
-       {
-               SMgrRelation srel = smgropen(parsed->xnodes[i], InvalidBackendId);
-               ForkNumber      fork;
-
-               for (fork = 0; fork <= MAX_FORKNUM; fork++)
-                       XLogDropRelation(parsed->xnodes[i], fork);
-               smgrdounlink(srel, true);
-               smgrclose(srel);
-       }
+       DropRelationFiles(parsed->xnodes, parsed->nrels, true);
 }
 
 void
index a94828b32c7339762feb75962ca6329812009f7f..bfa065d9fb82e7ecc050b76199dde89a0cd4751d 100644 (file)
@@ -26,6 +26,7 @@
 #include <sys/file.h>
 
 #include "miscadmin.h"
+#include "access/xlogutils.h"
 #include "access/xlog.h"
 #include "catalog/catalog.h"
 #include "portability/instr_time.h"
@@ -1701,6 +1702,43 @@ ForgetDatabaseFsyncRequests(Oid dbid)
        }
 }
 
+/*
+ * DropRelationFiles -- drop files of all given relations
+ */
+void
+DropRelationFiles(RelFileNode *delrels, int ndelrels, bool isRedo)
+{
+       SMgrRelation *srels;
+       int                     i;
+
+       srels = palloc(sizeof(SMgrRelation) * ndelrels);
+       for (i = 0; i < ndelrels; i++)
+       {
+               SMgrRelation srel = smgropen(delrels[i], InvalidBackendId);
+
+               if (isRedo)
+               {
+                       ForkNumber      fork;
+
+                       for (fork = 0; fork <= MAX_FORKNUM; fork++)
+                               XLogDropRelation(delrels[i], fork);
+               }
+               srels[i] = srel;
+       }
+
+       smgrdounlinkall(srels, ndelrels, isRedo);
+
+       /*
+        * Call smgrclose() in reverse order as when smgropen() is called.
+        * This trick enables remove_from_unowned_list() in smgrclose()
+        * to search the SMgrRelation from the unowned list,
+        * with O(1) performance.
+        */
+       for (i = ndelrels - 1; i >= 0; i--)
+               smgrclose(srels[i]);
+       pfree(srels);
+}
+
 
 /*
  *     _fdvec_alloc() -- Make a MdfdVec object.
index a8e7877f704f7982fed73690a4185e127de73170..38a4eaf24f236bed41ec081b8096591dce04e7ea 100644 (file)
@@ -139,6 +139,7 @@ extern void RememberFsyncRequest(RelFileNode rnode, ForkNumber forknum,
                                         BlockNumber segno);
 extern void ForgetRelationFsyncRequests(RelFileNode rnode, ForkNumber forknum);
 extern void ForgetDatabaseFsyncRequests(Oid dbid);
+extern void DropRelationFiles(RelFileNode *delrels, int ndelrels, bool isRedo);
 
 /* smgrtype.c */
 extern Datum smgrout(PG_FUNCTION_ARGS);