Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit71d05a2

Browse files
committed
pg_visibility: Add pg_truncate_visibility_map function.
This requires some core changes as well so that we can properlyWAL-log the truncation. Specifically, it changes the format of theXLOG_SMGR_TRUNCATE WAL record, so bump XLOG_PAGE_MAGIC.Patch by me, reviewed but not fully endorsed by Andres Freund.
1 parent54f5c51 commit71d05a2

File tree

8 files changed

+133
-13
lines changed

8 files changed

+133
-13
lines changed

‎contrib/pg_visibility/pg_visibility--1.0--1.1.sql

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,12 @@ RETURNS SETOF tid
1313
AS'MODULE_PATHNAME','pg_check_visible'
1414
LANGUAGE C STRICT;
1515

16+
CREATEFUNCTIONpg_truncate_visibility_map(regclass)
17+
RETURNS void
18+
AS'MODULE_PATHNAME','pg_truncate_visibility_map'
19+
LANGUAGE C STRICT
20+
PARALLEL UNSAFE;-- let's not make this any more dangerous
21+
1622
REVOKE ALLON FUNCTION pg_check_frozen(regclass)FROM PUBLIC;
1723
REVOKE ALLON FUNCTION pg_check_visible(regclass)FROM PUBLIC;
24+
REVOKE ALLON FUNCTION pg_truncate_visibility_map(regclass)FROM PUBLIC;

‎contrib/pg_visibility/pg_visibility--1.1.sql

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,13 @@ RETURNS SETOF tid
5757
AS'MODULE_PATHNAME','pg_check_visible'
5858
LANGUAGE C STRICT;
5959

60+
-- Truncate the visibility map fork.
61+
CREATEFUNCTIONpg_truncate_visibility_map(regclass)
62+
RETURNS void
63+
AS'MODULE_PATHNAME','pg_truncate_visibility_map'
64+
LANGUAGE C STRICT
65+
PARALLEL UNSAFE;-- let's not make this any more dangerous
66+
6067
-- Don't want these to be available to public.
6168
REVOKE ALLON FUNCTION pg_visibility_map(regclass,bigint)FROM PUBLIC;
6269
REVOKE ALLON FUNCTION pg_visibility(regclass,bigint)FROM PUBLIC;
@@ -65,3 +72,4 @@ REVOKE ALL ON FUNCTION pg_visibility(regclass) FROM PUBLIC;
6572
REVOKE ALLON FUNCTION pg_visibility_map_summary(regclass)FROM PUBLIC;
6673
REVOKE ALLON FUNCTION pg_check_frozen(regclass)FROM PUBLIC;
6774
REVOKE ALLON FUNCTION pg_check_visible(regclass)FROM PUBLIC;
75+
REVOKE ALLON FUNCTION pg_truncate_visibility_map(regclass)FROM PUBLIC;

‎contrib/pg_visibility/pg_visibility.c

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@
1111
#include"access/htup_details.h"
1212
#include"access/visibilitymap.h"
1313
#include"catalog/pg_type.h"
14+
#include"catalog/storage_xlog.h"
1415
#include"funcapi.h"
1516
#include"miscadmin.h"
1617
#include"storage/bufmgr.h"
1718
#include"storage/procarray.h"
19+
#include"storage/smgr.h"
1820
#include"utils/rel.h"
1921

2022
PG_MODULE_MAGIC;
@@ -40,6 +42,7 @@ PG_FUNCTION_INFO_V1(pg_visibility_rel);
4042
PG_FUNCTION_INFO_V1(pg_visibility_map_summary);
4143
PG_FUNCTION_INFO_V1(pg_check_frozen);
4244
PG_FUNCTION_INFO_V1(pg_check_visible);
45+
PG_FUNCTION_INFO_V1(pg_truncate_visibility_map);
4346

4447
staticTupleDescpg_visibility_tupdesc(boolinclude_blkno,boolinclude_pd);
4548
staticvbits*collect_visibility_data(Oidrelid,boolinclude_pd);
@@ -335,6 +338,75 @@ pg_check_visible(PG_FUNCTION_ARGS)
335338
SRF_RETURN_DONE(funcctx);
336339
}
337340

341+
/*
342+
* Remove the visibility map fork for a relation. If there turn out to be
343+
* any bugs in the visibility map code that require rebuilding the VM, this
344+
* provides users with a way to do it that is cleaner than shutting down the
345+
* server and removing files by hand.
346+
*
347+
* This is a cut-down version of RelationTruncate.
348+
*/
349+
Datum
350+
pg_truncate_visibility_map(PG_FUNCTION_ARGS)
351+
{
352+
Oidrelid=PG_GETARG_OID(0);
353+
Relationrel;
354+
355+
rel=relation_open(relid,AccessExclusiveLock);
356+
357+
if (rel->rd_rel->relkind!=RELKIND_RELATION&&
358+
rel->rd_rel->relkind!=RELKIND_MATVIEW&&
359+
rel->rd_rel->relkind!=RELKIND_TOASTVALUE)
360+
ereport(ERROR,
361+
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
362+
errmsg("\"%s\" is not a table, materialized view, or TOAST table",
363+
RelationGetRelationName(rel))));
364+
365+
RelationOpenSmgr(rel);
366+
rel->rd_smgr->smgr_vm_nblocks=InvalidBlockNumber;
367+
368+
visibilitymap_truncate(rel,0);
369+
370+
if (RelationNeedsWAL(rel))
371+
{
372+
xl_smgr_truncatexlrec;
373+
374+
xlrec.blkno=0;
375+
xlrec.rnode=rel->rd_node;
376+
xlrec.flags=SMGR_TRUNCATE_VM;
377+
378+
XLogBeginInsert();
379+
XLogRegisterData((char*)&xlrec,sizeof(xlrec));
380+
381+
XLogInsert(RM_SMGR_ID,XLOG_SMGR_TRUNCATE |XLR_SPECIAL_REL_UPDATE);
382+
}
383+
384+
/*
385+
* Release the lock right away, not at commit time.
386+
*
387+
* It would be a problem to release the lock prior to commit if this
388+
* truncate operation sends any transactional invalidation messages. Other
389+
* backends would potentially be able to lock the relation without
390+
* processing them in the window of time between when we release the lock
391+
* here and when we sent the messages at our eventual commit. However,
392+
* we're currently only sending a non-transactional smgr invalidation,
393+
* which will have been posted to shared memory immediately from within
394+
* visibilitymap_truncate. Therefore, there should be no race here.
395+
*
396+
* The reason why it's desirable to release the lock early here is because
397+
* of the possibility that someone will need to use this to blow away many
398+
* visibility map forks at once. If we can't release the lock until
399+
* commit time, the transaction doing this will accumulate
400+
* AccessExclusiveLocks on all of those relations at the same time, which
401+
* is undesirable. However, if this turns out to be unsafe we may have no
402+
* choice...
403+
*/
404+
relation_close(rel,AccessExclusiveLock);
405+
406+
/* Nothing to return. */
407+
PG_RETURN_VOID();
408+
}
409+
338410
/*
339411
* Helper function to construct whichever TupleDesc we need for a particular
340412
* call.

‎doc/src/sgml/pgvisibility.sgml

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,16 @@
99

1010
<para>
1111
The <filename>pg_visibility</> module provides a means for examining the
12-
visibility map (VM) and page-level visibility information.
12+
visibility map (VM) and page-level visibility information. It also
13+
provides functions to check the integrity of the visibility map and to
14+
force it to be rebuilt.
1315
</para>
1416

1517
<para>
16-
These routines return information about three different bits. The
17-
all-visible bit in the visibility map indicates that every tuple on
18-
a given page of a relation is visible to every current transaction. The
19-
all-frozen bit in the visibility map indicates that every tuple on the
18+
Three different bits are used to store information about page-level
19+
visibility. Theall-visible bit in the visibility map indicates that every
20+
tuple ona given page of a relation is visible to every current transaction.
21+
Theall-frozen bit in the visibility map indicates that every tuple on the
2022
page is frozen; that is, no future vacuum will need to modify the page
2123
until such time as a tuple is inserted, updated, deleted, or locked on
2224
that page. The page-level <literal>PD_ALL_VISIBLE</literal> bit has the
@@ -25,7 +27,8 @@
2527
will normally agree, but the page-level bit can sometimes be set while the
2628
visibility map bit is clear after a crash recovery; or they can disagree
2729
because of a change which occurs after <literal>pg_visibility</> examines
28-
the visibility map and before it examines the data page.
30+
the visibility map and before it examines the data page. Any event which
31+
causes data corruption can also cause these bits to disagree.
2932
</para>
3033

3134
<para>
@@ -118,6 +121,21 @@
118121
</para>
119122
</listitem>
120123
</varlistentry>
124+
125+
<varlistentry>
126+
<term><function>pg_truncate_visibility_map(regclass) returns void</function></term>
127+
128+
<listitem>
129+
<para>
130+
Truncates the visibility map for the given relation. This function
131+
is only expected to be useful if you suspect that the visibility map
132+
for the indicated relation is corrupt and wish to rebuild it. The first
133+
<command>VACUUM</> executed on the given relation after this function
134+
is executed will scan every page in the relation and rebuild the
135+
visibility map.
136+
</para>
137+
</listitem>
138+
</varlistentry>
121139
</variablelist>
122140

123141
<para>

‎src/backend/access/rmgrdesc/smgrdesc.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ smgr_desc(StringInfo buf, XLogReaderState *record)
3737
xl_smgr_truncate*xlrec= (xl_smgr_truncate*)rec;
3838
char*path=relpathperm(xlrec->rnode,MAIN_FORKNUM);
3939

40-
appendStringInfo(buf,"%s to %u blocks",path,xlrec->blkno);
40+
appendStringInfo(buf,"%s to %u blocks flags %d",path,
41+
xlrec->blkno,xlrec->flags);
4142
pfree(path);
4243
}
4344
}

‎src/backend/catalog/storage.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ RelationTruncate(Relation rel, BlockNumber nblocks)
268268

269269
xlrec.blkno=nblocks;
270270
xlrec.rnode=rel->rd_node;
271+
xlrec.flags=SMGR_TRUNCATE_ALL;
271272

272273
XLogBeginInsert();
273274
XLogRegisterData((char*)&xlrec,sizeof(xlrec));
@@ -522,17 +523,22 @@ smgr_redo(XLogReaderState *record)
522523
*/
523524
XLogFlush(lsn);
524525

525-
smgrtruncate(reln,MAIN_FORKNUM,xlrec->blkno);
526+
if ((xlrec->flags&SMGR_TRUNCATE_HEAP)!=0)
527+
{
528+
smgrtruncate(reln,MAIN_FORKNUM,xlrec->blkno);
526529

527-
/* Also tell xlogutils.c about it */
528-
XLogTruncateRelation(xlrec->rnode,MAIN_FORKNUM,xlrec->blkno);
530+
/* Also tell xlogutils.c about it */
531+
XLogTruncateRelation(xlrec->rnode,MAIN_FORKNUM,xlrec->blkno);
532+
}
529533

530534
/* Truncate FSM and VM too */
531535
rel=CreateFakeRelcacheEntry(xlrec->rnode);
532536

533-
if (smgrexists(reln,FSM_FORKNUM))
537+
if ((xlrec->flags&SMGR_TRUNCATE_FSM)!=0&&
538+
smgrexists(reln,FSM_FORKNUM))
534539
FreeSpaceMapTruncateRel(rel,xlrec->blkno);
535-
if (smgrexists(reln,VISIBILITYMAP_FORKNUM))
540+
if ((xlrec->flags&SMGR_TRUNCATE_VM)!=0&&
541+
smgrexists(reln,VISIBILITYMAP_FORKNUM))
536542
visibilitymap_truncate(rel,xlrec->blkno);
537543

538544
FreeFakeRelcacheEntry(rel);

‎src/include/access/xlog_internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
/*
3232
* Each page of XLOG file has a header like this:
3333
*/
34-
#defineXLOG_PAGE_MAGIC0xD091/* can be used as WAL version indicator */
34+
#defineXLOG_PAGE_MAGIC0xD092/* can be used as WAL version indicator */
3535

3636
typedefstructXLogPageHeaderData
3737
{

‎src/include/catalog/storage_xlog.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,18 @@ typedef struct xl_smgr_create
3636
ForkNumberforkNum;
3737
}xl_smgr_create;
3838

39+
/* flags for xl_smgr_truncate */
40+
#defineSMGR_TRUNCATE_HEAP0x0001
41+
#defineSMGR_TRUNCATE_VM0x0002
42+
#defineSMGR_TRUNCATE_FSM0x0004
43+
#defineSMGR_TRUNCATE_ALL\
44+
(SMGR_TRUNCATE_HEAP|SMGR_TRUNCATE_VM|SMGR_TRUNCATE_FSM)
45+
3946
typedefstructxl_smgr_truncate
4047
{
4148
BlockNumberblkno;
4249
RelFileNodernode;
50+
intflags;
4351
}xl_smgr_truncate;
4452

4553
externvoidlog_smgrcreate(RelFileNode*rnode,ForkNumberforkNum);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp