!1103 修复反复对分区表执行split、merge后,执行vacuum freeze pg_partition报错的问题
Merge pull request !1103 from 杨皓/partition-vacuum-problem
This commit is contained in:
22
src/common/backend/utils/cache/partcache.cpp
vendored
22
src/common/backend/utils/cache/partcache.cpp
vendored
@ -1827,6 +1827,28 @@ bool PartitionInvisibleMetadataKeep(Datum datumRelOptions)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Check whether a partition is properly used. */
|
||||
bool PartitionParentOidIsLive(Datum parentDatum)
|
||||
{
|
||||
Oid parentid = InvalidOid;
|
||||
HeapTuple partTuple = NULL;
|
||||
|
||||
if (!PointerIsValid(parentDatum)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
parentid = DatumGetObjectId(parentDatum);
|
||||
|
||||
/* Get table information from syscache */
|
||||
partTuple = SearchSysCache1WithLogLevel(RELOID, ObjectIdGetDatum(parentid), LOG);
|
||||
if (HeapTupleIsValid(partTuple)) {
|
||||
ReleaseSysCache(partTuple);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* In pg_partition, search all tuples (visible and invisible) containing wait_clean_gpi=y
|
||||
* in reloptios of one partitioed relation and set wait_clean_gpi=n
|
||||
|
||||
@ -113,6 +113,7 @@ typedef struct LVRelStats {
|
||||
double* new_idx_tuples;
|
||||
bool* idx_estimated;
|
||||
Oid currVacuumPartOid; /* current lazy vacuum partition oid */
|
||||
bool hasKeepInvisbleTuples;
|
||||
} LVRelStats;
|
||||
|
||||
typedef struct ValPrefetchList {
|
||||
@ -396,6 +397,7 @@ void lazy_vacuum_rel(Relation onerel, VacuumStmt* vacstmt, BufferAccessStrategy
|
||||
vacrelstats->num_index_scans = 0;
|
||||
vacrelstats->pages_removed = 0;
|
||||
vacrelstats->lock_waiter_detected = false;
|
||||
vacrelstats->hasKeepInvisbleTuples = false;
|
||||
|
||||
/* Open all indexes of the relation */
|
||||
if (RelationIsPartition(onerel)) {
|
||||
@ -445,8 +447,9 @@ void lazy_vacuum_rel(Relation onerel, VacuumStmt* vacstmt, BufferAccessStrategy
|
||||
new_rel_allvisible = new_rel_pages;
|
||||
|
||||
new_frozen_xid = u_sess->cmd_cxt.FreezeLimit;
|
||||
if (vacrelstats->scanned_pages < vacrelstats->rel_pages)
|
||||
if (vacrelstats->scanned_pages < vacrelstats->rel_pages || vacrelstats->hasKeepInvisbleTuples) {
|
||||
new_frozen_xid = InvalidTransactionId;
|
||||
}
|
||||
|
||||
if (RelationIsPartition(onerel)) {
|
||||
Assert(vacstmt->onepart != NULL);
|
||||
@ -898,6 +901,7 @@ static IndexBulkDeleteResult** lazy_scan_heap(
|
||||
OffsetNumber offnum, maxoff;
|
||||
bool tupgone = false;
|
||||
bool hastup = false;
|
||||
bool keepThisInvisbleTuple = false;
|
||||
int prev_dead_count;
|
||||
OffsetNumber frozen[MaxOffsetNumber];
|
||||
int nfrozen;
|
||||
@ -1165,6 +1169,7 @@ static IndexBulkDeleteResult** lazy_scan_heap(
|
||||
tuple.t_bucketId = RelationGetBktid(onerel);
|
||||
HeapTupleCopyBaseFromPage(&tuple, page);
|
||||
tupgone = false;
|
||||
keepThisInvisbleTuple = false;
|
||||
|
||||
if (u_sess->attr.attr_storage.enable_debug_vacuum)
|
||||
t_thrd.utils_cxt.pRelatedRel = onerel;
|
||||
@ -1187,11 +1192,12 @@ static IndexBulkDeleteResult** lazy_scan_heap(
|
||||
* cheaper to get rid of it in the next pruning pass than
|
||||
* to treat it like an indexed tuple.
|
||||
*/
|
||||
if (HeapTupleIsHotUpdated(&tuple) || HeapTupleIsHeapOnly(&tuple) ||
|
||||
HeapKeepInvisbleTuple(&tuple, RelationGetDescr(onerel)))
|
||||
keepThisInvisbleTuple = HeapKeepInvisbleTuple(&tuple, RelationGetDescr(onerel));
|
||||
if (HeapTupleIsHotUpdated(&tuple) || HeapTupleIsHeapOnly(&tuple) || keepThisInvisbleTuple) {
|
||||
nkeep += 1;
|
||||
else
|
||||
} else {
|
||||
tupgone = true; /* we can delete the tuple */
|
||||
}
|
||||
all_visible = false;
|
||||
break;
|
||||
case HEAPTUPLE_LIVE:
|
||||
@ -1265,6 +1271,8 @@ static IndexBulkDeleteResult** lazy_scan_heap(
|
||||
|
||||
tups_vacuumed += 1;
|
||||
has_dead_tuples = true;
|
||||
} else if (keepThisInvisbleTuple) {
|
||||
vacrelstats->hasKeepInvisbleTuples = true;
|
||||
} else {
|
||||
num_tuples += 1;
|
||||
hastup = true;
|
||||
|
||||
@ -3232,13 +3232,15 @@ void heap_slot_store_heap_tuple(HeapTuple tuple, TupleTableSlot* slot, Buffer bu
|
||||
bool HeapKeepInvisbleTuple(HeapTuple tuple, TupleDesc tupleDesc, KeepInvisbleTupleFunc checkKeepFunc)
|
||||
{
|
||||
static KeepInvisbleOpt keepInvisibleArray[] = {
|
||||
{PartitionRelationId, Anum_pg_partition_reloptions, PartitionInvisibleMetadataKeep}};
|
||||
{PartitionRelationId, Anum_pg_partition_reloptions, PartitionInvisibleMetadataKeep},
|
||||
{PartitionRelationId, Anum_pg_partition_parentid, PartitionParentOidIsLive}};
|
||||
|
||||
bool ret = true;
|
||||
for (int i = 0; i < (int)lengthof(keepInvisibleArray); i++) {
|
||||
bool isNull = false;
|
||||
KeepInvisbleOpt keepOpt = keepInvisibleArray[i];
|
||||
|
||||
if (keepOpt.tableOid != tuple->t_tableOid) {
|
||||
if (keepOpt.tableOid != tuple->t_tableOid || !ret) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -3248,13 +3250,13 @@ bool HeapKeepInvisbleTuple(HeapTuple tuple, TupleDesc tupleDesc, KeepInvisbleTup
|
||||
}
|
||||
|
||||
if (checkKeepFunc != NULL) {
|
||||
return checkKeepFunc(checkDatum);
|
||||
ret &= checkKeepFunc(checkDatum);
|
||||
} else if (keepOpt.checkKeepFunc != NULL) {
|
||||
return keepOpt.checkKeepFunc(checkDatum);
|
||||
ret &= keepOpt.checkKeepFunc(checkDatum);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -89,6 +89,7 @@ extern Datum SetWaitCleanGpiRelOptions(Datum oldOptions, bool enable);
|
||||
extern void PartitionedSetWaitCleanGpi(const char* parentName, Oid parentPartOid, bool enable, bool inplace);
|
||||
extern void PartitionSetWaitCleanGpi(Oid partOid, bool enable, bool inplace);
|
||||
extern bool PartitionInvisibleMetadataKeep(Datum datumRelOptions);
|
||||
extern bool PartitionParentOidIsLive(Datum parentDatum);
|
||||
extern void PartitionedSetEnabledClean(Oid parentOid);
|
||||
extern void PartitionSetEnabledClean(
|
||||
Oid parentOid, const Bitmapset* cleanedParts, const Bitmapset* invisibleParts, bool updatePartitioned);
|
||||
|
||||
@ -1232,6 +1232,7 @@ select count(*) from alter_table where INV_WAREHOUSE_SK < 20000;
|
||||
4000
|
||||
(1 row)
|
||||
|
||||
vacuum freeze pg_partition;
|
||||
--clean
|
||||
drop index if exists local_exchange_table_index1;
|
||||
drop table if exists exchange_table;
|
||||
|
||||
@ -289,6 +289,8 @@ explain (costs off) select count(*) from alter_table where INV_WAREHOUSE_SK < 20
|
||||
|
||||
select count(*) from alter_table where INV_WAREHOUSE_SK < 20000;
|
||||
|
||||
vacuum freeze pg_partition;
|
||||
|
||||
--clean
|
||||
drop index if exists local_exchange_table_index1;
|
||||
drop table if exists exchange_table;
|
||||
|
||||
Reference in New Issue
Block a user