mirror of
https://github.com/postgres/postgres.git
synced 2025-06-14 18:42:34 +03:00
Set cutoff xmin more aggressively when vacuuming a temporary table.
Since other sessions aren't allowed to look into a temporary table of our own session, we do not need to worry about the global xmin horizon when setting the vacuum XID cutoff. Indeed, if we're not inside a transaction block, we may set oldestXmin to be the next XID, because there cannot be any in-doubt tuples in a temp table, nor any tuples that are dead but still visible to some snapshot of our transaction. (VACUUM, of course, is never inside a transaction block; but we need to test that because CLUSTER shares the same code.) This approach allows us to always clean out a temp table completely during VACUUM, independently of concurrent activity. Aside from being useful in its own right, that simplifies building reproducible test cases. Discussion: https://postgr.es/m/3490536.1598629609@sss.pgh.pa.us
This commit is contained in:
@ -67,10 +67,13 @@ typedef struct
|
||||
} RelToCluster;
|
||||
|
||||
|
||||
static void rebuild_relation(Relation OldHeap, Oid indexOid, bool verbose);
|
||||
static void rebuild_relation(Relation OldHeap, Oid indexOid,
|
||||
bool isTopLevel, bool verbose);
|
||||
static void copy_table_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex,
|
||||
bool verbose, bool *pSwapToastByContent,
|
||||
TransactionId *pFreezeXid, MultiXactId *pCutoffMulti);
|
||||
bool isTopLevel, bool verbose,
|
||||
bool *pSwapToastByContent,
|
||||
TransactionId *pFreezeXid,
|
||||
MultiXactId *pCutoffMulti);
|
||||
static List *get_tables_to_cluster(MemoryContext cluster_context);
|
||||
|
||||
|
||||
@ -170,7 +173,7 @@ cluster(ClusterStmt *stmt, bool isTopLevel)
|
||||
table_close(rel, NoLock);
|
||||
|
||||
/* Do the job. */
|
||||
cluster_rel(tableOid, indexOid, stmt->options);
|
||||
cluster_rel(tableOid, indexOid, stmt->options, isTopLevel);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -219,7 +222,8 @@ cluster(ClusterStmt *stmt, bool isTopLevel)
|
||||
PushActiveSnapshot(GetTransactionSnapshot());
|
||||
/* Do the job. */
|
||||
cluster_rel(rvtc->tableOid, rvtc->indexOid,
|
||||
stmt->options | CLUOPT_RECHECK);
|
||||
stmt->options | CLUOPT_RECHECK,
|
||||
isTopLevel);
|
||||
PopActiveSnapshot();
|
||||
CommitTransactionCommand();
|
||||
}
|
||||
@ -250,7 +254,7 @@ cluster(ClusterStmt *stmt, bool isTopLevel)
|
||||
* and error messages should refer to the operation as VACUUM not CLUSTER.
|
||||
*/
|
||||
void
|
||||
cluster_rel(Oid tableOid, Oid indexOid, int options)
|
||||
cluster_rel(Oid tableOid, Oid indexOid, int options, bool isTopLevel)
|
||||
{
|
||||
Relation OldHeap;
|
||||
bool verbose = ((options & CLUOPT_VERBOSE) != 0);
|
||||
@ -400,7 +404,7 @@ cluster_rel(Oid tableOid, Oid indexOid, int options)
|
||||
TransferPredicateLocksToHeapRelation(OldHeap);
|
||||
|
||||
/* rebuild_relation does all the dirty work */
|
||||
rebuild_relation(OldHeap, indexOid, verbose);
|
||||
rebuild_relation(OldHeap, indexOid, isTopLevel, verbose);
|
||||
|
||||
/* NB: rebuild_relation does table_close() on OldHeap */
|
||||
|
||||
@ -545,11 +549,12 @@ mark_index_clustered(Relation rel, Oid indexOid, bool is_internal)
|
||||
*
|
||||
* OldHeap: table to rebuild --- must be opened and exclusive-locked!
|
||||
* indexOid: index to cluster by, or InvalidOid to rewrite in physical order.
|
||||
* isTopLevel: should be passed down from ProcessUtility.
|
||||
*
|
||||
* NB: this routine closes OldHeap at the right time; caller should not.
|
||||
*/
|
||||
static void
|
||||
rebuild_relation(Relation OldHeap, Oid indexOid, bool verbose)
|
||||
rebuild_relation(Relation OldHeap, Oid indexOid, bool isTopLevel, bool verbose)
|
||||
{
|
||||
Oid tableOid = RelationGetRelid(OldHeap);
|
||||
Oid tableSpace = OldHeap->rd_rel->reltablespace;
|
||||
@ -577,7 +582,7 @@ rebuild_relation(Relation OldHeap, Oid indexOid, bool verbose)
|
||||
AccessExclusiveLock);
|
||||
|
||||
/* Copy the heap data into the new table in the desired order */
|
||||
copy_table_data(OIDNewHeap, tableOid, indexOid, verbose,
|
||||
copy_table_data(OIDNewHeap, tableOid, indexOid, isTopLevel, verbose,
|
||||
&swap_toast_by_content, &frozenXid, &cutoffMulti);
|
||||
|
||||
/*
|
||||
@ -728,7 +733,8 @@ make_new_heap(Oid OIDOldHeap, Oid NewTableSpace, char relpersistence,
|
||||
* *pCutoffMulti receives the MultiXactId used as a cutoff point.
|
||||
*/
|
||||
static void
|
||||
copy_table_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose,
|
||||
copy_table_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex,
|
||||
bool isTopLevel, bool verbose,
|
||||
bool *pSwapToastByContent, TransactionId *pFreezeXid,
|
||||
MultiXactId *pCutoffMulti)
|
||||
{
|
||||
@ -826,7 +832,7 @@ copy_table_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose,
|
||||
* Since we're going to rewrite the whole table anyway, there's no reason
|
||||
* not to be aggressive about this.
|
||||
*/
|
||||
vacuum_set_xid_limits(OldHeap, 0, 0, 0, 0,
|
||||
vacuum_set_xid_limits(OldHeap, 0, 0, 0, 0, isTopLevel,
|
||||
&OldestXmin, &FreezeXid, NULL, &MultiXactCutoff,
|
||||
NULL);
|
||||
|
||||
|
Reference in New Issue
Block a user