mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03:00
pg_visibility: Add pg_truncate_visibility_map function.
This requires some core changes as well so that we can properly WAL-log the truncation. Specifically, it changes the format of the XLOG_SMGR_TRUNCATE WAL record, so bump XLOG_PAGE_MAGIC. Patch by me, reviewed but not fully endorsed by Andres Freund.
This commit is contained in:
@ -11,10 +11,12 @@
|
||||
#include "access/htup_details.h"
|
||||
#include "access/visibilitymap.h"
|
||||
#include "catalog/pg_type.h"
|
||||
#include "catalog/storage_xlog.h"
|
||||
#include "funcapi.h"
|
||||
#include "miscadmin.h"
|
||||
#include "storage/bufmgr.h"
|
||||
#include "storage/procarray.h"
|
||||
#include "storage/smgr.h"
|
||||
#include "utils/rel.h"
|
||||
|
||||
PG_MODULE_MAGIC;
|
||||
@ -40,6 +42,7 @@ PG_FUNCTION_INFO_V1(pg_visibility_rel);
|
||||
PG_FUNCTION_INFO_V1(pg_visibility_map_summary);
|
||||
PG_FUNCTION_INFO_V1(pg_check_frozen);
|
||||
PG_FUNCTION_INFO_V1(pg_check_visible);
|
||||
PG_FUNCTION_INFO_V1(pg_truncate_visibility_map);
|
||||
|
||||
static TupleDesc pg_visibility_tupdesc(bool include_blkno, bool include_pd);
|
||||
static vbits *collect_visibility_data(Oid relid, bool include_pd);
|
||||
@ -335,6 +338,75 @@ pg_check_visible(PG_FUNCTION_ARGS)
|
||||
SRF_RETURN_DONE(funcctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove the visibility map fork for a relation. If there turn out to be
|
||||
* any bugs in the visibility map code that require rebuilding the VM, this
|
||||
* provides users with a way to do it that is cleaner than shutting down the
|
||||
* server and removing files by hand.
|
||||
*
|
||||
* This is a cut-down version of RelationTruncate.
|
||||
*/
|
||||
Datum
|
||||
pg_truncate_visibility_map(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Oid relid = PG_GETARG_OID(0);
|
||||
Relation rel;
|
||||
|
||||
rel = relation_open(relid, AccessExclusiveLock);
|
||||
|
||||
if (rel->rd_rel->relkind != RELKIND_RELATION &&
|
||||
rel->rd_rel->relkind != RELKIND_MATVIEW &&
|
||||
rel->rd_rel->relkind != RELKIND_TOASTVALUE)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("\"%s\" is not a table, materialized view, or TOAST table",
|
||||
RelationGetRelationName(rel))));
|
||||
|
||||
RelationOpenSmgr(rel);
|
||||
rel->rd_smgr->smgr_vm_nblocks = InvalidBlockNumber;
|
||||
|
||||
visibilitymap_truncate(rel, 0);
|
||||
|
||||
if (RelationNeedsWAL(rel))
|
||||
{
|
||||
xl_smgr_truncate xlrec;
|
||||
|
||||
xlrec.blkno = 0;
|
||||
xlrec.rnode = rel->rd_node;
|
||||
xlrec.flags = SMGR_TRUNCATE_VM;
|
||||
|
||||
XLogBeginInsert();
|
||||
XLogRegisterData((char *) &xlrec, sizeof(xlrec));
|
||||
|
||||
XLogInsert(RM_SMGR_ID, XLOG_SMGR_TRUNCATE | XLR_SPECIAL_REL_UPDATE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Release the lock right away, not at commit time.
|
||||
*
|
||||
* It would be a problem to release the lock prior to commit if this
|
||||
* truncate operation sends any transactional invalidation messages. Other
|
||||
* backends would potentially be able to lock the relation without
|
||||
* processing them in the window of time between when we release the lock
|
||||
* here and when we sent the messages at our eventual commit. However,
|
||||
* we're currently only sending a non-transactional smgr invalidation,
|
||||
* which will have been posted to shared memory immediately from within
|
||||
* visibilitymap_truncate. Therefore, there should be no race here.
|
||||
*
|
||||
* The reason why it's desirable to release the lock early here is because
|
||||
* of the possibility that someone will need to use this to blow away many
|
||||
* visibility map forks at once. If we can't release the lock until
|
||||
* commit time, the transaction doing this will accumulate
|
||||
* AccessExclusiveLocks on all of those relations at the same time, which
|
||||
* is undesirable. However, if this turns out to be unsafe we may have no
|
||||
* choice...
|
||||
*/
|
||||
relation_close(rel, AccessExclusiveLock);
|
||||
|
||||
/* Nothing to return. */
|
||||
PG_RETURN_VOID();
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function to construct whichever TupleDesc we need for a particular
|
||||
* call.
|
||||
|
Reference in New Issue
Block a user