diff options
author | Robert Haas <rhaas@postgresql.org> | 2016-06-17 17:37:30 -0400 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2016-06-17 17:37:30 -0400 |
commit | 71d05a2c7b82379bb1013a0e338906349c54ed85 (patch) | |
tree | 53a862320e1b58955449b7238d6f725cf1d954b4 /contrib/pg_visibility/pg_visibility.c | |
parent | 54f5c5150fa05d7ad15f8406debd5a2b394885b5 (diff) |
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.
Diffstat (limited to 'contrib/pg_visibility/pg_visibility.c')
-rw-r--r-- | contrib/pg_visibility/pg_visibility.c | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/contrib/pg_visibility/pg_visibility.c b/contrib/pg_visibility/pg_visibility.c index abb92f388a3..70340666630 100644 --- a/contrib/pg_visibility/pg_visibility.c +++ b/contrib/pg_visibility/pg_visibility.c @@ -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); @@ -336,6 +339,75 @@ pg_check_visible(PG_FUNCTION_ARGS) } /* + * 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. */ |