]> 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:23:46 +0000 (02:23 +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 a9ef1b3d73cafa3ba13d7498d99a4305fd659194..e8d4e37fe3072c881ad66e0e2d6b7c309e96a7ec 100644 (file)
@@ -1456,7 +1456,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
@@ -1549,13 +1548,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 8e6aef332cb09afb51c70f871c00ee5e7baee4dd..1da1f13ef33f0c882d0203db3fc5e579654293ed 100644 (file)
@@ -5516,7 +5516,6 @@ xact_redo_commit(xl_xact_parsed_commit *parsed,
                                 RepOriginId origin_id)
 {
        TransactionId max_xid;
-       int                     i;
        TimestampTz commit_time;
 
        Assert(TransactionIdIsValid(xid));
@@ -5635,16 +5634,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);
        }
 
        /*
@@ -5683,7 +5674,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;
 
        Assert(TransactionIdIsValid(xid));
@@ -5748,16 +5738,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 2ec103e60479739c357ab2f67b6bc6e1dc9d34cf..f4374d077be981af072366fda757e7d2a9972de2 100644 (file)
@@ -26,6 +26,7 @@
 #include <sys/file.h>
 
 #include "miscadmin.h"
+#include "access/xlogutils.h"
 #include "access/xlog.h"
 #include "pgstat.h"
 #include "portability/instr_time.h"
@@ -1703,6 +1704,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_resize() -- Resize the fork's open segments array
index 558e4d8518b19193af3688469181cfd19b70133f..c843bbc9692096112b0bfada541d314bbd2a4235 100644 (file)
@@ -143,5 +143,6 @@ 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);
 
 #endif                                                 /* SMGR_H */