Skip to content

Commit 8463be0

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 c2c69d4 commit 8463be0

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
@@ -1390,7 +1390,6 @@ FinishPreparedTransaction(const char *gid, bool isCommit)
13901390
RelFileNode *delrels;
13911391
int ndelrels;
13921392
SharedInvalidationMessage *invalmsgs;
1393-
int i;
13941393

13951394
/*
13961395
* Validate the GID, and lock the GXACT to ensure that two backends do not
@@ -1482,13 +1481,9 @@ FinishPreparedTransaction(const char *gid, bool isCommit)
14821481
delrels = abortrels;
14831482
ndelrels = hdr->nabortrels;
14841483
}
1485-
for (i = 0; i < ndelrels; i++)
1486-
{
1487-
SMgrRelation srel = smgropen(delrels[i], InvalidBackendId);
14881484

1489-
smgrdounlink(srel, false);
1490-
smgrclose(srel);
1491-
}
1485+
/* Make sure files supposed to be dropped are dropped */
1486+
DropRelationFiles(delrels, ndelrels, false);
14921487

14931488
/*
14941489
* Handle cache invalidation messages.

src/backend/access/transam/xact.c

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5373,7 +5373,6 @@ xact_redo_commit(xl_xact_parsed_commit *parsed,
53735373
RepOriginId origin_id)
53745374
{
53755375
TransactionId max_xid;
5376-
int i;
53775376
TimestampTz commit_time;
53785377

53795378
Assert(TransactionIdIsValid(xid));
@@ -5494,16 +5493,8 @@ xact_redo_commit(xl_xact_parsed_commit *parsed,
54945493
*/
54955494
XLogFlush(lsn);
54965495

5497-
for (i = 0; i < parsed->nrels; i++)
5498-
{
5499-
SMgrRelation srel = smgropen(parsed->xnodes[i], InvalidBackendId);
5500-
ForkNumber fork;
5501-
5502-
for (fork = 0; fork <= MAX_FORKNUM; fork++)
5503-
XLogDropRelation(parsed->xnodes[i], fork);
5504-
smgrdounlink(srel, true);
5505-
smgrclose(srel);
5506-
}
5496+
/* Make sure files supposed to be dropped are dropped */
5497+
DropRelationFiles(parsed->xnodes, parsed->nrels, true);
55075498
}
55085499

55095500
/*
@@ -5542,7 +5533,6 @@ xact_redo_commit(xl_xact_parsed_commit *parsed,
55425533
static void
55435534
xact_redo_abort(xl_xact_parsed_abort *parsed, TransactionId xid)
55445535
{
5545-
int i;
55465536
TransactionId max_xid;
55475537

55485538
Assert(TransactionIdIsValid(xid));
@@ -5607,16 +5597,7 @@ xact_redo_abort(xl_xact_parsed_abort *parsed, TransactionId xid)
56075597
}
56085598

56095599
/* Make sure files supposed to be dropped are dropped */
5610-
for (i = 0; i < parsed->nrels; i++)
5611-
{
5612-
SMgrRelation srel = smgropen(parsed->xnodes[i], InvalidBackendId);
5613-
ForkNumber fork;
5614-
5615-
for (fork = 0; fork <= MAX_FORKNUM; fork++)
5616-
XLogDropRelation(parsed->xnodes[i], fork);
5617-
smgrdounlink(srel, true);
5618-
smgrclose(srel);
5619-
}
5600+
DropRelationFiles(parsed->xnodes, parsed->nrels, true);
56205601
}
56215602

56225603
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 "pgstat.h"
@@ -1704,6 +1705,43 @@ ForgetDatabaseFsyncRequests(Oid dbid)
17041705
}
17051706
}
17061707

1708+
/*
1709+
* DropRelationFiles -- drop files of all given relations
1710+
*/
1711+
void
1712+
DropRelationFiles(RelFileNode *delrels, int ndelrels, bool isRedo)
1713+
{
1714+
SMgrRelation *srels;
1715+
int i;
1716+
1717+
srels = palloc(sizeof(SMgrRelation) * ndelrels);
1718+
for (i = 0; i < ndelrels; i++)
1719+
{
1720+
SMgrRelation srel = smgropen(delrels[i], InvalidBackendId);
1721+
1722+
if (isRedo)
1723+
{
1724+
ForkNumber fork;
1725+
1726+
for (fork = 0; fork <= MAX_FORKNUM; fork++)
1727+
XLogDropRelation(delrels[i], fork);
1728+
}
1729+
srels[i] = srel;
1730+
}
1731+
1732+
smgrdounlinkall(srels, ndelrels, isRedo);
1733+
1734+
/*
1735+
* Call smgrclose() in reverse order as when smgropen() is called.
1736+
* This trick enables remove_from_unowned_list() in smgrclose()
1737+
* to search the SMgrRelation from the unowned list,
1738+
* with O(1) performance.
1739+
*/
1740+
for (i = ndelrels - 1; i >= 0; i--)
1741+
smgrclose(srels[i]);
1742+
pfree(srels);
1743+
}
1744+
17071745

17081746
/*
17091747
* _fdvec_resize() -- Resize the fork's open segments array

src/include/storage/smgr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,5 +143,6 @@ extern void RememberFsyncRequest(RelFileNode rnode, ForkNumber forknum,
143143
BlockNumber segno);
144144
extern void ForgetRelationFsyncRequests(RelFileNode rnode, ForkNumber forknum);
145145
extern void ForgetDatabaseFsyncRequests(Oid dbid);
146+
extern void DropRelationFiles(RelFileNode *delrels, int ndelrels, bool isRedo);
146147

147148
#endif /* SMGR_H */

0 commit comments

Comments
 (0)