!1103 修复反复对分区表执行split、merge后,执行vacuum freeze pg_partition报错的问题

Merge pull request !1103 from 杨皓/partition-vacuum-problem
This commit is contained in:
opengauss-bot
2021-07-22 11:17:10 +00:00
committed by Gitee
6 changed files with 45 additions and 9 deletions

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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;