Skip to content

Commit 62c2fe6

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 2a4dca9 commit 62c2fe6

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
@@ -1362,7 +1362,6 @@ FinishPreparedTransaction(const char *gid, bool isCommit)
13621362
RelFileNode *delrels;
13631363
int ndelrels;
13641364
SharedInvalidationMessage *invalmsgs;
1365-
int i;
13661365

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

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

14631458
/*
14641459
* Handle cache invalidation messages.

src/backend/access/transam/xact.c

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4710,7 +4710,6 @@ xact_redo_commit_internal(TransactionId xid, XLogRecPtr lsn,
47104710
uint32 xinfo)
47114711
{
47124712
TransactionId max_xid;
4713-
int i;
47144713

47154714
max_xid = TransactionIdLatest(xid, nsubxacts, sub_xids);
47164715

@@ -4805,16 +4804,8 @@ xact_redo_commit_internal(TransactionId xid, XLogRecPtr lsn,
48054804
*/
48064805
XLogFlush(lsn);
48074806

4808-
for (i = 0; i < nrels; i++)
4809-
{
4810-
SMgrRelation srel = smgropen(xnodes[i], InvalidBackendId);
4811-
ForkNumber fork;
4812-
4813-
for (fork = 0; fork <= MAX_FORKNUM; fork++)
4814-
XLogDropRelation(xnodes[i], fork);
4815-
smgrdounlink(srel, true);
4816-
smgrclose(srel);
4817-
}
4807+
/* Make sure files supposed to be dropped are dropped */
4808+
DropRelationFiles(xnodes, nrels, true);
48184809
}
48194810

48204811
/*
@@ -4886,7 +4877,6 @@ xact_redo_abort(xl_xact_abort *xlrec, TransactionId xid)
48864877
{
48874878
TransactionId *sub_xids;
48884879
TransactionId max_xid;
4889-
int i;
48904880

48914881
sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
48924882
max_xid = TransactionIdLatest(xid, xlrec->nsubxacts, sub_xids);
@@ -4945,16 +4935,7 @@ xact_redo_abort(xl_xact_abort *xlrec, TransactionId xid)
49454935
}
49464936

49474937
/* Make sure files supposed to be dropped are dropped */
4948-
for (i = 0; i < xlrec->nrels; i++)
4949-
{
4950-
SMgrRelation srel = smgropen(xlrec->xnodes[i], InvalidBackendId);
4951-
ForkNumber fork;
4952-
4953-
for (fork = 0; fork <= MAX_FORKNUM; fork++)
4954-
XLogDropRelation(xlrec->xnodes[i], fork);
4955-
smgrdounlink(srel, true);
4956-
smgrclose(srel);
4957-
}
4938+
DropRelationFiles(xlrec->xnodes, xlrec->nrels, true);
49584939
}
49594940

49604941
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 "portability/instr_time.h"
@@ -1625,6 +1626,43 @@ ForgetDatabaseFsyncRequests(Oid dbid)
16251626
}
16261627
}
16271628

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

16291667
/*
16301668
* _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)