Skip to content

Commit 7ffe012

Browse files
committed
Improve the performance of relation deletes during recovery.
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 279628a, 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
1 parent 7fbbbe1 commit 7ffe012

File tree

4 files changed

+44
-29
lines changed

4 files changed

+44
-29
lines changed

src/backend/access/transam/twophase.c

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1361,7 +1361,6 @@ FinishPreparedTransaction(const char *gid, bool isCommit)
13611361
RelFileNode *delrels;
13621362
int ndelrels;
13631363
SharedInvalidationMessage *invalmsgs;
1364-
int i;
13651364

13661365
/*
13671366
* Validate the GID, and lock the GXACT to ensure that two backends do not
@@ -1451,13 +1450,9 @@ FinishPreparedTransaction(const char *gid, bool isCommit)
14511450
delrels = abortrels;
14521451
ndelrels = hdr->nabortrels;
14531452
}
1454-
for (i = 0; i < ndelrels; i++)
1455-
{
1456-
SMgrRelation srel = smgropen(delrels[i], InvalidBackendId);
14571453

1458-
smgrdounlink(srel, false);
1459-
smgrclose(srel);
1460-
}
1454+
/* Make sure files supposed to be dropped are dropped */
1455+
DropRelationFiles(delrels, ndelrels, false);
14611456

14621457
/*
14631458
* Handle cache invalidation messages.

src/backend/access/transam/xact.c

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4642,7 +4642,6 @@ xact_redo_commit_internal(TransactionId xid, XLogRecPtr lsn,
46424642
uint32 xinfo)
46434643
{
46444644
TransactionId max_xid;
4645-
int i;
46464645

46474646
max_xid = TransactionIdLatest(xid, nsubxacts, sub_xids);
46484647

@@ -4737,16 +4736,8 @@ xact_redo_commit_internal(TransactionId xid, XLogRecPtr lsn,
47374736
*/
47384737
XLogFlush(lsn);
47394738

4740-
for (i = 0; i < nrels; i++)
4741-
{
4742-
SMgrRelation srel = smgropen(xnodes[i], InvalidBackendId);
4743-
ForkNumber fork;
4744-
4745-
for (fork = 0; fork <= MAX_FORKNUM; fork++)
4746-
XLogDropRelation(xnodes[i], fork);
4747-
smgrdounlink(srel, true);
4748-
smgrclose(srel);
4749-
}
4739+
/* Make sure files supposed to be dropped are dropped */
4740+
DropRelationFiles(xnodes, nrels, true);
47504741
}
47514742

47524743
/*
@@ -4818,7 +4809,6 @@ xact_redo_abort(xl_xact_abort *xlrec, TransactionId xid)
48184809
{
48194810
TransactionId *sub_xids;
48204811
TransactionId max_xid;
4821-
int i;
48224812

48234813
sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
48244814
max_xid = TransactionIdLatest(xid, xlrec->nsubxacts, sub_xids);
@@ -4877,16 +4867,7 @@ xact_redo_abort(xl_xact_abort *xlrec, TransactionId xid)
48774867
}
48784868

48794869
/* Make sure files supposed to be dropped are dropped */
4880-
for (i = 0; i < xlrec->nrels; i++)
4881-
{
4882-
SMgrRelation srel = smgropen(xlrec->xnodes[i], InvalidBackendId);
4883-
ForkNumber fork;
4884-
4885-
for (fork = 0; fork <= MAX_FORKNUM; fork++)
4886-
XLogDropRelation(xlrec->xnodes[i], fork);
4887-
smgrdounlink(srel, true);
4888-
smgrclose(srel);
4889-
}
4870+
DropRelationFiles(xlrec->xnodes, xlrec->nrels, true);
48904871
}
48914872

48924873
void

src/backend/storage/smgr/md.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <sys/file.h>
2727

2828
#include "miscadmin.h"
29+
#include "access/xlogutils.h"
2930
#include "access/xlog.h"
3031
#include "catalog/catalog.h"
3132
#include "common/relpath.h"
@@ -1626,6 +1627,43 @@ ForgetDatabaseFsyncRequests(Oid dbid)
16261627
}
16271628
}
16281629

1630+
/*
1631+
* DropRelationFiles -- drop files of all given relations
1632+
*/
1633+
void
1634+
DropRelationFiles(RelFileNode *delrels, int ndelrels, bool isRedo)
1635+
{
1636+
SMgrRelation *srels;
1637+
int i;
1638+
1639+
srels = palloc(sizeof(SMgrRelation) * ndelrels);
1640+
for (i = 0; i < ndelrels; i++)
1641+
{
1642+
SMgrRelation srel = smgropen(delrels[i], InvalidBackendId);
1643+
1644+
if (isRedo)
1645+
{
1646+
ForkNumber fork;
1647+
1648+
for (fork = 0; fork <= MAX_FORKNUM; fork++)
1649+
XLogDropRelation(delrels[i], fork);
1650+
}
1651+
srels[i] = srel;
1652+
}
1653+
1654+
smgrdounlinkall(srels, ndelrels, isRedo);
1655+
1656+
/*
1657+
* Call smgrclose() in reverse order as when smgropen() is called.
1658+
* This trick enables remove_from_unowned_list() in smgrclose()
1659+
* to search the SMgrRelation from the unowned list,
1660+
* with O(1) performance.
1661+
*/
1662+
for (i = ndelrels - 1; i >= 0; i--)
1663+
smgrclose(srels[i]);
1664+
pfree(srels);
1665+
}
1666+
16291667

16301668
/*
16311669
* _fdvec_alloc() -- Make a MdfdVec object.

src/include/storage/smgr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ extern void RememberFsyncRequest(RelFileNode rnode, ForkNumber forknum,
135135
BlockNumber segno);
136136
extern void ForgetRelationFsyncRequests(RelFileNode rnode, ForkNumber forknum);
137137
extern void ForgetDatabaseFsyncRequests(Oid dbid);
138+
extern void DropRelationFiles(RelFileNode *delrels, int ndelrels, bool isRedo);
138139

139140
/* smgrtype.c */
140141
extern Datum smgrout(PG_FUNCTION_ARGS);

0 commit comments

Comments
 (0)