mirror of https://github.com/citusdata/citus.git
address feedback
parent
b0fa3d91bc
commit
2d16b0fd9e
|
@ -95,8 +95,6 @@ char *EnableManualMetadataChangesForUser = "";
|
||||||
int MetadataSyncTransMode = METADATA_SYNC_TRANSACTIONAL;
|
int MetadataSyncTransMode = METADATA_SYNC_TRANSACTIONAL;
|
||||||
|
|
||||||
|
|
||||||
static Datum citus_internal_add_shard_metadata_internal(PG_FUNCTION_ARGS,
|
|
||||||
bool expectNeedsSeparateNode);
|
|
||||||
static void EnsureObjectMetadataIsSane(int distributionArgumentIndex,
|
static void EnsureObjectMetadataIsSane(int distributionArgumentIndex,
|
||||||
int colocationId);
|
int colocationId);
|
||||||
static List * GetFunctionDependenciesForObjects(ObjectAddress *objectAddress);
|
static List * GetFunctionDependenciesForObjects(ObjectAddress *objectAddress);
|
||||||
|
@ -169,7 +167,6 @@ PG_FUNCTION_INFO_V1(worker_record_sequence_dependency);
|
||||||
PG_FUNCTION_INFO_V1(citus_internal_add_partition_metadata);
|
PG_FUNCTION_INFO_V1(citus_internal_add_partition_metadata);
|
||||||
PG_FUNCTION_INFO_V1(citus_internal_delete_partition_metadata);
|
PG_FUNCTION_INFO_V1(citus_internal_delete_partition_metadata);
|
||||||
PG_FUNCTION_INFO_V1(citus_internal_add_shard_metadata);
|
PG_FUNCTION_INFO_V1(citus_internal_add_shard_metadata);
|
||||||
PG_FUNCTION_INFO_V1(citus_internal_add_shard_metadata_legacy);
|
|
||||||
PG_FUNCTION_INFO_V1(citus_internal_add_placement_metadata);
|
PG_FUNCTION_INFO_V1(citus_internal_add_placement_metadata);
|
||||||
PG_FUNCTION_INFO_V1(citus_internal_delete_placement_metadata);
|
PG_FUNCTION_INFO_V1(citus_internal_delete_placement_metadata);
|
||||||
PG_FUNCTION_INFO_V1(citus_internal_add_placement_metadata_legacy);
|
PG_FUNCTION_INFO_V1(citus_internal_add_placement_metadata_legacy);
|
||||||
|
@ -3226,33 +3223,6 @@ citus_internal_delete_partition_metadata(PG_FUNCTION_ARGS)
|
||||||
*/
|
*/
|
||||||
Datum
|
Datum
|
||||||
citus_internal_add_shard_metadata(PG_FUNCTION_ARGS)
|
citus_internal_add_shard_metadata(PG_FUNCTION_ARGS)
|
||||||
{
|
|
||||||
bool expectNeedsSeparateNode = true;
|
|
||||||
return citus_internal_add_shard_metadata_internal(fcinfo, expectNeedsSeparateNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* citus_internal_add_shard_metadata is an internal UDF to
|
|
||||||
* add a row to pg_dist_shard, but without the needs_separate_node
|
|
||||||
* parameter.
|
|
||||||
*/
|
|
||||||
Datum
|
|
||||||
citus_internal_add_shard_metadata_legacy(PG_FUNCTION_ARGS)
|
|
||||||
{
|
|
||||||
bool expectNeedsSeparateNode = false;
|
|
||||||
return citus_internal_add_shard_metadata_internal(fcinfo, expectNeedsSeparateNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* citus_internal_add_shard_metadata_internal is a helper function for
|
|
||||||
* citus_internal_add_shard_metadata and citus_internal_add_shard_metadata_legacy
|
|
||||||
* functions.
|
|
||||||
*/
|
|
||||||
static Datum
|
|
||||||
citus_internal_add_shard_metadata_internal(PG_FUNCTION_ARGS,
|
|
||||||
bool expectNeedsSeparateNode)
|
|
||||||
{
|
{
|
||||||
CheckCitusVersion(ERROR);
|
CheckCitusVersion(ERROR);
|
||||||
|
|
||||||
|
@ -3277,12 +3247,8 @@ citus_internal_add_shard_metadata_internal(PG_FUNCTION_ARGS,
|
||||||
shardMaxValue = PG_GETARG_TEXT_P(4);
|
shardMaxValue = PG_GETARG_TEXT_P(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool needsSeparateNode = false;
|
|
||||||
if (expectNeedsSeparateNode)
|
|
||||||
{
|
|
||||||
PG_ENSURE_ARGNOTNULL(5, "needs separate node");
|
PG_ENSURE_ARGNOTNULL(5, "needs separate node");
|
||||||
needsSeparateNode = PG_GETARG_BOOL(5);
|
bool needsSeparateNode = PG_GETARG_BOOL(5);
|
||||||
}
|
|
||||||
|
|
||||||
/* only owner of the table (or superuser) is allowed to add the Citus metadata */
|
/* only owner of the table (or superuser) is allowed to add the Citus metadata */
|
||||||
EnsureTableOwner(relationId);
|
EnsureTableOwner(relationId);
|
||||||
|
|
|
@ -115,7 +115,7 @@ static void AppendShardIdNameValues(StringInfo selectQuery, ShardInterval *shard
|
||||||
static HeapTuple CreateDiskSpaceTuple(TupleDesc tupleDesc, uint64 availableBytes,
|
static HeapTuple CreateDiskSpaceTuple(TupleDesc tupleDesc, uint64 availableBytes,
|
||||||
uint64 totalBytes);
|
uint64 totalBytes);
|
||||||
static bool GetLocalDiskSpaceStats(uint64 *availableBytes, uint64 *totalBytes);
|
static bool GetLocalDiskSpaceStats(uint64 *availableBytes, uint64 *totalBytes);
|
||||||
static void citus_shard_property_set_anti_affinity(uint64 shardId, bool enabled);
|
static void CitusShardPropertySetAntiAffinity(uint64 shardId, bool enabled);
|
||||||
static void ShardGroupSetNeedsSeparateNodeGlobally(uint64 shardId, bool enabled);
|
static void ShardGroupSetNeedsSeparateNodeGlobally(uint64 shardId, bool enabled);
|
||||||
static void ShardSetNeedsSeparateNode(uint64 shardId, bool enabled);
|
static void ShardSetNeedsSeparateNode(uint64 shardId, bool enabled);
|
||||||
static BackgroundTask * DeformBackgroundTaskHeapTuple(TupleDesc tupleDescriptor,
|
static BackgroundTask * DeformBackgroundTaskHeapTuple(TupleDesc tupleDescriptor,
|
||||||
|
@ -373,17 +373,15 @@ citus_shard_property_set(PG_FUNCTION_ARGS)
|
||||||
PG_ENSURE_ARGNOTNULL(0, "shard_id");
|
PG_ENSURE_ARGNOTNULL(0, "shard_id");
|
||||||
uint64 shardId = PG_GETARG_INT64(0);
|
uint64 shardId = PG_GETARG_INT64(0);
|
||||||
|
|
||||||
if (!ShardExists(shardId))
|
/* RelationIdForShard() first checks whether the shard id is valid */
|
||||||
{
|
|
||||||
ereport(ERROR, (errmsg("shard %lu does not exist", shardId)));
|
|
||||||
}
|
|
||||||
|
|
||||||
Oid distributedRelationId = RelationIdForShard(shardId);
|
Oid distributedRelationId = RelationIdForShard(shardId);
|
||||||
|
|
||||||
List *colocatedTableList = ColocatedTableList(distributedRelationId);
|
List *colocatedTableList = ColocatedTableList(distributedRelationId);
|
||||||
|
colocatedTableList = SortList(colocatedTableList, CompareOids);
|
||||||
EnsureTableListOwner(colocatedTableList);
|
EnsureTableListOwner(colocatedTableList);
|
||||||
|
|
||||||
AcquirePlacementColocationLock(distributedRelationId, ExclusiveLock,
|
AcquirePlacementColocationLock(distributedRelationId, ExclusiveLock,
|
||||||
"set anti affinity property for a shard of");
|
"set a property for a shard of");
|
||||||
|
|
||||||
Oid colocatedTableId = InvalidOid;
|
Oid colocatedTableId = InvalidOid;
|
||||||
foreach_oid(colocatedTableId, colocatedTableList)
|
foreach_oid(colocatedTableId, colocatedTableList)
|
||||||
|
@ -394,7 +392,7 @@ citus_shard_property_set(PG_FUNCTION_ARGS)
|
||||||
if (!PG_ARGISNULL(1))
|
if (!PG_ARGISNULL(1))
|
||||||
{
|
{
|
||||||
bool antiAffinity = PG_GETARG_BOOL(1);
|
bool antiAffinity = PG_GETARG_BOOL(1);
|
||||||
citus_shard_property_set_anti_affinity(shardId, antiAffinity);
|
CitusShardPropertySetAntiAffinity(shardId, antiAffinity);
|
||||||
}
|
}
|
||||||
|
|
||||||
PG_RETURN_VOID();
|
PG_RETURN_VOID();
|
||||||
|
@ -402,19 +400,19 @@ citus_shard_property_set(PG_FUNCTION_ARGS)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* citus_shard_property_set_anti_affinity is an helper function for
|
* CitusShardPropertySetAntiAffinity is an helper function for
|
||||||
* citus_shard_property_set UDF to set anti_affinity property for given
|
* citus_shard_property_set UDF to set anti_affinity property for given
|
||||||
* shard.
|
* shard.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
citus_shard_property_set_anti_affinity(uint64 shardId, bool enabled)
|
CitusShardPropertySetAntiAffinity(uint64 shardId, bool enabled)
|
||||||
{
|
{
|
||||||
Oid distributedRelationId = RelationIdForShard(shardId);
|
Oid distributedRelationId = RelationIdForShard(shardId);
|
||||||
if (!IsCitusTableType(distributedRelationId, HASH_DISTRIBUTED) &&
|
if (!IsCitusTableType(distributedRelationId, HASH_DISTRIBUTED) &&
|
||||||
!IsCitusTableType(distributedRelationId, SINGLE_SHARD_DISTRIBUTED))
|
!IsCitusTableType(distributedRelationId, SINGLE_SHARD_DISTRIBUTED))
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errmsg("shard isolation is only supported for hash "
|
ereport(ERROR, (errmsg("setting anti-affinity property is only "
|
||||||
"distributed tables")));
|
"supported for hash distributed tables")));
|
||||||
}
|
}
|
||||||
|
|
||||||
ShardGroupSetNeedsSeparateNodeGlobally(shardId, enabled);
|
ShardGroupSetNeedsSeparateNodeGlobally(shardId, enabled);
|
||||||
|
@ -1502,18 +1500,17 @@ ShardLength(uint64 shardId)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NodeGroupGetSeparatedShardPlacementGroup returns the shard placement group
|
* NodeGroupGetSeparatedShardgroupPlacement returns the shard group placement
|
||||||
* that given node group is used to separate from others. Returns NULL if this
|
* that given node group is used to separate from others. Returns NULL if this
|
||||||
* node is not used to separate a shard placement group.
|
* node is not used to separate a shard group placement.
|
||||||
*/
|
*/
|
||||||
ShardPlacementGroup *
|
ShardgroupPlacement *
|
||||||
NodeGroupGetSeparatedShardPlacementGroup(int32 groupId)
|
NodeGroupGetSeparatedShardgroupPlacement(int32 groupId)
|
||||||
{
|
{
|
||||||
ShardPlacementGroup *nodeShardPlacementGroup = NULL;
|
ShardgroupPlacement *nodeShardgroupPlacement = NULL;
|
||||||
bool shardPlacementGroupNeedsSeparateNode = false;
|
bool shardgroupPlacementNeedsSeparateNode = false;
|
||||||
|
|
||||||
bool indexOK = true;
|
bool indexOK = true;
|
||||||
int scanKeyCount = 1;
|
|
||||||
ScanKeyData scanKey[1];
|
ScanKeyData scanKey[1];
|
||||||
|
|
||||||
Relation pgDistPlacement = table_open(DistPlacementRelationId(),
|
Relation pgDistPlacement = table_open(DistPlacementRelationId(),
|
||||||
|
@ -1524,10 +1521,10 @@ NodeGroupGetSeparatedShardPlacementGroup(int32 groupId)
|
||||||
SysScanDesc scanDescriptor = systable_beginscan(pgDistPlacement,
|
SysScanDesc scanDescriptor = systable_beginscan(pgDistPlacement,
|
||||||
DistPlacementGroupidIndexId(),
|
DistPlacementGroupidIndexId(),
|
||||||
indexOK,
|
indexOK,
|
||||||
NULL, scanKeyCount, scanKey);
|
NULL, lengthof(scanKey), scanKey);
|
||||||
|
|
||||||
HeapTuple heapTuple = systable_getnext(scanDescriptor);
|
HeapTuple heapTuple = NULL;
|
||||||
while (HeapTupleIsValid(heapTuple))
|
while (HeapTupleIsValid(heapTuple = systable_getnext(scanDescriptor)))
|
||||||
{
|
{
|
||||||
TupleDesc tupleDescriptor = RelationGetDescr(pgDistPlacement);
|
TupleDesc tupleDescriptor = RelationGetDescr(pgDistPlacement);
|
||||||
|
|
||||||
|
@ -1538,46 +1535,49 @@ NodeGroupGetSeparatedShardPlacementGroup(int32 groupId)
|
||||||
Oid citusTableId = shardInterval->relationId;
|
Oid citusTableId = shardInterval->relationId;
|
||||||
if (!IsCitusTableType(citusTableId, DISTRIBUTED_TABLE))
|
if (!IsCitusTableType(citusTableId, DISTRIBUTED_TABLE))
|
||||||
{
|
{
|
||||||
heapTuple = systable_getnext(scanDescriptor);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShardPlacementGroup *shardPlacementGroup =
|
ShardgroupPlacement *shardgroupPlacement =
|
||||||
GetShardPlacementGroupForPlacement(placement->shardId,
|
GetShardgroupPlacementForPlacement(placement->shardId,
|
||||||
placement->placementId);
|
placement->placementId);
|
||||||
|
|
||||||
if (nodeShardPlacementGroup &&
|
if (nodeShardgroupPlacement &&
|
||||||
!ShardPlacementGroupsSame(shardPlacementGroup,
|
!ShardgroupPlacementsSame(shardgroupPlacement,
|
||||||
nodeShardPlacementGroup))
|
nodeShardgroupPlacement))
|
||||||
{
|
{
|
||||||
nodeShardPlacementGroup = NULL;
|
/*
|
||||||
|
* If we have more than one shardgroup placement on the node,
|
||||||
|
* then this means that the node is not actually used to separate
|
||||||
|
* a shardgroup placement.
|
||||||
|
*/
|
||||||
|
nodeShardgroupPlacement = NULL;
|
||||||
|
shardgroupPlacementNeedsSeparateNode = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeShardPlacementGroup = shardPlacementGroup;
|
nodeShardgroupPlacement = shardgroupPlacement;
|
||||||
shardPlacementGroupNeedsSeparateNode = shardInterval->needsSeparateNode;
|
shardgroupPlacementNeedsSeparateNode = shardInterval->needsSeparateNode;
|
||||||
|
|
||||||
heapTuple = systable_getnext(scanDescriptor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
systable_endscan(scanDescriptor);
|
systable_endscan(scanDescriptor);
|
||||||
table_close(pgDistPlacement, NoLock);
|
table_close(pgDistPlacement, NoLock);
|
||||||
|
|
||||||
if (!shardPlacementGroupNeedsSeparateNode)
|
if (!shardgroupPlacementNeedsSeparateNode)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nodeShardPlacementGroup;
|
return nodeShardgroupPlacement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ShardPlacementGroupsSame returns true if two shard placement groups are the same.
|
* ShardgroupPlacementsSame returns true if two shardgroup placements are the same.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
ShardPlacementGroupsSame(const ShardPlacementGroup *leftGroup,
|
ShardgroupPlacementsSame(const ShardgroupPlacement *leftGroup,
|
||||||
const ShardPlacementGroup *rightGroup)
|
const ShardgroupPlacement *rightGroup)
|
||||||
{
|
{
|
||||||
return leftGroup->colocatationId == rightGroup->colocatationId &&
|
return leftGroup->colocatationId == rightGroup->colocatationId &&
|
||||||
leftGroup->shardIntervalIndex == rightGroup->shardIntervalIndex &&
|
leftGroup->shardIntervalIndex == rightGroup->shardIntervalIndex &&
|
||||||
|
@ -1618,16 +1618,61 @@ NodeGroupHasShardPlacements(int32 groupId)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GetShardPlacementGroupForPlacement returns ShardPlacementGroup that placement
|
* NodeGroupHasDistributedTableShardPlacements returns whether any active
|
||||||
|
* distributed table shards are placed on the group
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
NodeGroupHasDistributedTableShardPlacements(int32 groupId)
|
||||||
|
{
|
||||||
|
bool nodeGroupHasDistributedTableShardPlacements = false;
|
||||||
|
|
||||||
|
Relation pgPlacement = table_open(DistPlacementRelationId(), AccessShareLock);
|
||||||
|
|
||||||
|
ScanKeyData scanKey[1];
|
||||||
|
ScanKeyInit(&scanKey[0], Anum_pg_dist_placement_groupid,
|
||||||
|
BTEqualStrategyNumber, F_INT4EQ, Int32GetDatum(groupId));
|
||||||
|
|
||||||
|
bool indexOK = true;
|
||||||
|
SysScanDesc scanDescriptor = systable_beginscan(pgPlacement,
|
||||||
|
DistPlacementGroupidIndexId(),
|
||||||
|
indexOK,
|
||||||
|
NULL, lengthof(scanKey), scanKey);
|
||||||
|
|
||||||
|
HeapTuple heapTuple = NULL;
|
||||||
|
while (HeapTupleIsValid(heapTuple = systable_getnext(scanDescriptor)))
|
||||||
|
{
|
||||||
|
TupleDesc tupleDescriptor = RelationGetDescr(pgPlacement);
|
||||||
|
|
||||||
|
GroupShardPlacement *placement =
|
||||||
|
TupleToGroupShardPlacement(tupleDescriptor, heapTuple);
|
||||||
|
|
||||||
|
ShardInterval *shardInterval = LoadShardInterval(placement->shardId);
|
||||||
|
Oid citusTableId = shardInterval->relationId;
|
||||||
|
if (IsCitusTableType(citusTableId, DISTRIBUTED_TABLE))
|
||||||
|
{
|
||||||
|
nodeGroupHasDistributedTableShardPlacements = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
systable_endscan(scanDescriptor);
|
||||||
|
table_close(pgPlacement, NoLock);
|
||||||
|
|
||||||
|
return nodeGroupHasDistributedTableShardPlacements;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GetShardgroupPlacementForPlacement returns ShardgroupPlacement that placement
|
||||||
* with given shardId & placementId belongs to.
|
* with given shardId & placementId belongs to.
|
||||||
*/
|
*/
|
||||||
ShardPlacementGroup *
|
ShardgroupPlacement *
|
||||||
GetShardPlacementGroupForPlacement(uint64 shardId, uint64 placementId)
|
GetShardgroupPlacementForPlacement(uint64 shardId, uint64 placementId)
|
||||||
{
|
{
|
||||||
ShardPlacement *shardPlacement = LoadShardPlacement(shardId, placementId);
|
ShardPlacement *shardPlacement = LoadShardPlacement(shardId, placementId);
|
||||||
ShardInterval *shardInterval = LoadShardInterval(shardId);
|
ShardInterval *shardInterval = LoadShardInterval(shardId);
|
||||||
|
|
||||||
ShardPlacementGroup *placementGroup = palloc(sizeof(ShardPlacementGroup));
|
ShardgroupPlacement *placementGroup = palloc(sizeof(ShardgroupPlacement));
|
||||||
placementGroup->colocatationId = shardPlacement->colocationGroupId;
|
placementGroup->colocatationId = shardPlacement->colocationGroupId;
|
||||||
placementGroup->shardIntervalIndex = shardInterval->shardIndex;
|
placementGroup->shardIntervalIndex = shardInterval->shardIndex;
|
||||||
placementGroup->nodeGroupId = shardPlacement->groupId;
|
placementGroup->nodeGroupId = shardPlacement->groupId;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*-------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* rebalancer_placement_isolation.c
|
* rebalancer_placement_separation.c
|
||||||
* Routines to determine which worker node should be used to separate
|
* Routines to determine which worker node should be used to separate
|
||||||
* a colocated set of shard placements that need separate nodes.
|
* a colocated set of shard placements that need separate nodes.
|
||||||
*
|
*
|
||||||
|
@ -10,6 +10,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
|
|
||||||
#include "nodes/pg_list.h"
|
#include "nodes/pg_list.h"
|
||||||
#include "utils/hsearch.h"
|
#include "utils/hsearch.h"
|
||||||
#include "utils/lsyscache.h"
|
#include "utils/lsyscache.h"
|
||||||
|
@ -20,12 +21,17 @@
|
||||||
#include "distributed/metadata_cache.h"
|
#include "distributed/metadata_cache.h"
|
||||||
#include "distributed/metadata_utility.h"
|
#include "distributed/metadata_utility.h"
|
||||||
#include "distributed/multi_physical_planner.h"
|
#include "distributed/multi_physical_planner.h"
|
||||||
#include "distributed/rebalancer_placement_isolation.h"
|
#include "distributed/rebalancer_placement_separation.h"
|
||||||
#include "distributed/shard_rebalancer.h"
|
#include "distributed/shard_rebalancer.h"
|
||||||
|
|
||||||
|
|
||||||
struct RebalancerPlacementIsolationContext
|
struct RebalancerPlacementSeparationContext
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* Hash table where each entry is of the form NodeToPlacementGroupHashEntry,
|
||||||
|
* meaning that each entry maps the node with nodeGroupId to
|
||||||
|
* a NodeToPlacementGroupHashEntry.
|
||||||
|
*/
|
||||||
HTAB *nodePlacementGroupHash;
|
HTAB *nodePlacementGroupHash;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -35,7 +41,7 @@ struct RebalancerPlacementIsolationContext
|
||||||
* placement group that is determined to be separated from other shards in
|
* placement group that is determined to be separated from other shards in
|
||||||
* the cluster via that node.
|
* the cluster via that node.
|
||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct NodeToPlacementGroupHashEntry
|
||||||
{
|
{
|
||||||
/* hash key -- group id of the node */
|
/* hash key -- group id of the node */
|
||||||
int32 nodeGroupId;
|
int32 nodeGroupId;
|
||||||
|
@ -49,39 +55,37 @@ typedef struct
|
||||||
bool shouldHaveShards;
|
bool shouldHaveShards;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Whether given node is allowed to separate any shard placement groups.
|
* Whether given node is allowed to separate any shardgroup placements.
|
||||||
*/
|
*/
|
||||||
bool allowedToSeparateAnyPlacementGroup;
|
bool allowedToSeparateAnyPlacementGroup;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Shard placement group that is assigned to this node to be separated
|
* Shardgroup placement that is assigned to this node to be separated
|
||||||
* from others in the cluster.
|
* from others in the cluster.
|
||||||
*
|
*
|
||||||
* NULL if no shard placement group is assigned yet.
|
* NULL if no shardgroup placement is assigned yet.
|
||||||
*/
|
*/
|
||||||
ShardPlacementGroup *assignedPlacementGroup;
|
ShardgroupPlacement *assignedPlacementGroup;
|
||||||
} NodeToPlacementGroupHashEntry;
|
} NodeToPlacementGroupHashEntry;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Routines to prepare a hash table where each entry is of type
|
* Routines to prepare RebalancerPlacementSeparationContext.
|
||||||
* NodeToPlacementGroupHashEntry.
|
|
||||||
*/
|
*/
|
||||||
static void NodeToPlacementGroupHashInit(HTAB *nodePlacementGroupHash,
|
static void InitRebalancerPlacementSeparationContext(
|
||||||
|
RebalancerPlacementSeparationContext *context,
|
||||||
List *activeWorkerNodeList,
|
List *activeWorkerNodeList,
|
||||||
List *rebalancePlacementList,
|
List *rebalancePlacementList,
|
||||||
WorkerNode *drainWorkerNode);
|
WorkerNode *drainWorkerNode);
|
||||||
static void NodeToPlacementGroupHashAssignNodes(HTAB *nodePlacementGroupHash,
|
static void TryAssignPlacementGroupsToNodeGroups(
|
||||||
|
RebalancerPlacementSeparationContext *context,
|
||||||
List *activeWorkerNodeList,
|
List *activeWorkerNodeList,
|
||||||
List *rebalancePlacementList,
|
List *rebalancePlacementList,
|
||||||
FmgrInfo *shardAllowedOnNodeUDF);
|
FmgrInfo *shardAllowedOnNodeUDF);
|
||||||
static bool NodeToPlacementGroupHashAssignNode(HTAB *nodePlacementGroupHash,
|
static bool TryAssignPlacementGroupToNodeGroup(
|
||||||
int32 nodeGroupId,
|
RebalancerPlacementSeparationContext *context,
|
||||||
|
int32 candidateNodeGroupId,
|
||||||
ShardPlacement *shardPlacement,
|
ShardPlacement *shardPlacement,
|
||||||
FmgrInfo *shardAllowedOnNodeUDF);
|
FmgrInfo *shardAllowedOnNodeUDF);
|
||||||
static NodeToPlacementGroupHashEntry * NodeToPlacementGroupHashGetNodeWithGroupId(
|
|
||||||
HTAB *nodePlacementGroupHash,
|
|
||||||
int32
|
|
||||||
nodeGroupId);
|
|
||||||
|
|
||||||
|
|
||||||
/* other helpers */
|
/* other helpers */
|
||||||
|
@ -90,12 +94,12 @@ static int WorkerNodeListGetNodeWithGroupId(List *workerNodeList, int32 nodeGrou
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PrepareRebalancerPlacementIsolationContext creates RebalancerPlacementIsolationContext
|
* PrepareRebalancerPlacementSeparationContext creates RebalancerPlacementSeparationContext
|
||||||
* that keeps track of which worker nodes are used to separate which shard placement groups
|
* that keeps track of which worker nodes are used to separate which shardgroup placements
|
||||||
* that need separate nodes.
|
* that need separate nodes.
|
||||||
*/
|
*/
|
||||||
RebalancerPlacementIsolationContext *
|
RebalancerPlacementSeparationContext *
|
||||||
PrepareRebalancerPlacementIsolationContext(List *activeWorkerNodeList,
|
PrepareRebalancerPlacementSeparationContext(List *activeWorkerNodeList,
|
||||||
List *rebalancePlacementList,
|
List *rebalancePlacementList,
|
||||||
WorkerNode *drainWorkerNode,
|
WorkerNode *drainWorkerNode,
|
||||||
FmgrInfo *shardAllowedOnNodeUDF)
|
FmgrInfo *shardAllowedOnNodeUDF)
|
||||||
|
@ -105,34 +109,39 @@ PrepareRebalancerPlacementIsolationContext(List *activeWorkerNodeList,
|
||||||
"NodeToPlacementGroupHash",
|
"NodeToPlacementGroupHash",
|
||||||
list_length(activeWorkerNodeList));
|
list_length(activeWorkerNodeList));
|
||||||
|
|
||||||
|
RebalancerPlacementSeparationContext *context =
|
||||||
|
palloc(sizeof(RebalancerPlacementSeparationContext));
|
||||||
|
context->nodePlacementGroupHash = nodePlacementGroupHash;
|
||||||
|
|
||||||
activeWorkerNodeList = SortList(activeWorkerNodeList, CompareWorkerNodes);
|
activeWorkerNodeList = SortList(activeWorkerNodeList, CompareWorkerNodes);
|
||||||
rebalancePlacementList = SortList(rebalancePlacementList, CompareShardPlacements);
|
rebalancePlacementList = SortList(rebalancePlacementList, CompareShardPlacements);
|
||||||
|
|
||||||
NodeToPlacementGroupHashInit(nodePlacementGroupHash, activeWorkerNodeList,
|
InitRebalancerPlacementSeparationContext(context, activeWorkerNodeList,
|
||||||
rebalancePlacementList, drainWorkerNode);
|
rebalancePlacementList, drainWorkerNode);
|
||||||
|
|
||||||
NodeToPlacementGroupHashAssignNodes(nodePlacementGroupHash,
|
TryAssignPlacementGroupsToNodeGroups(context,
|
||||||
activeWorkerNodeList,
|
activeWorkerNodeList,
|
||||||
rebalancePlacementList,
|
rebalancePlacementList,
|
||||||
shardAllowedOnNodeUDF);
|
shardAllowedOnNodeUDF);
|
||||||
|
|
||||||
RebalancerPlacementIsolationContext *context =
|
|
||||||
palloc(sizeof(RebalancerPlacementIsolationContext));
|
|
||||||
context->nodePlacementGroupHash = nodePlacementGroupHash;
|
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NodeToPlacementGroupHashInit initializes given hash table where each
|
* InitRebalancerPlacementSeparationContext initializes given
|
||||||
* entry is of type NodeToPlacementGroupHashEntry by using given list
|
* RebalancerPlacementSeparationContext by using given list
|
||||||
* of worker nodes and the worker node that is being drained, if specified.
|
* of worker nodes and the worker node that is being drained,
|
||||||
|
* if specified.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
NodeToPlacementGroupHashInit(HTAB *nodePlacementGroupHash, List *activeWorkerNodeList,
|
InitRebalancerPlacementSeparationContext(RebalancerPlacementSeparationContext *context,
|
||||||
List *rebalancePlacementList, WorkerNode *drainWorkerNode)
|
List *activeWorkerNodeList,
|
||||||
|
List *rebalancePlacementList,
|
||||||
|
WorkerNode *drainWorkerNode)
|
||||||
{
|
{
|
||||||
|
HTAB *nodePlacementGroupHash = context->nodePlacementGroupHash;
|
||||||
|
|
||||||
List *placementListUniqueNodeGroupIds =
|
List *placementListUniqueNodeGroupIds =
|
||||||
PlacementListGetUniqueNodeGroupIds(rebalancePlacementList);
|
PlacementListGetUniqueNodeGroupIds(rebalancePlacementList);
|
||||||
|
|
||||||
|
@ -143,8 +152,6 @@ NodeToPlacementGroupHashInit(HTAB *nodePlacementGroupHash, List *activeWorkerNod
|
||||||
hash_search(nodePlacementGroupHash, &workerNode->groupId, HASH_ENTER,
|
hash_search(nodePlacementGroupHash, &workerNode->groupId, HASH_ENTER,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
nodePlacementGroupHashEntry->nodeGroupId = workerNode->groupId;
|
|
||||||
|
|
||||||
bool shouldHaveShards = workerNode->shouldHaveShards;
|
bool shouldHaveShards = workerNode->shouldHaveShards;
|
||||||
if (drainWorkerNode && drainWorkerNode->groupId == workerNode->groupId)
|
if (drainWorkerNode && drainWorkerNode->groupId == workerNode->groupId)
|
||||||
{
|
{
|
||||||
|
@ -183,50 +190,40 @@ NodeToPlacementGroupHashInit(HTAB *nodePlacementGroupHash, List *activeWorkerNod
|
||||||
|
|
||||||
if (!shouldHaveShards)
|
if (!shouldHaveShards)
|
||||||
{
|
{
|
||||||
/* we can't assing any shard placement groups to the node anyway */
|
/* we can't assing any shardgroup placements to the node anyway */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (list_length(placementListUniqueNodeGroupIds) == list_length(
|
if (list_member_int(placementListUniqueNodeGroupIds, workerNode->groupId))
|
||||||
activeWorkerNodeList))
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* list_member_oid() check would return true for all placements then.
|
|
||||||
* This means that all the nodes are of type D.
|
|
||||||
*/
|
|
||||||
Assert(list_member_oid(placementListUniqueNodeGroupIds, workerNode->groupId));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (list_member_oid(placementListUniqueNodeGroupIds, workerNode->groupId))
|
|
||||||
{
|
{
|
||||||
/* node is of type D */
|
/* node is of type D */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShardPlacementGroup *separatedShardPlacementGroup =
|
ShardgroupPlacement *separatedShardgroupPlacement =
|
||||||
NodeGroupGetSeparatedShardPlacementGroup(
|
NodeGroupGetSeparatedShardgroupPlacement(
|
||||||
nodePlacementGroupHashEntry->nodeGroupId);
|
nodePlacementGroupHashEntry->nodeGroupId);
|
||||||
if (separatedShardPlacementGroup)
|
if (separatedShardgroupPlacement)
|
||||||
{
|
{
|
||||||
nodePlacementGroupHashEntry->assignedPlacementGroup =
|
nodePlacementGroupHashEntry->assignedPlacementGroup =
|
||||||
separatedShardPlacementGroup;
|
separatedShardgroupPlacement;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nodePlacementGroupHashEntry->allowedToSeparateAnyPlacementGroup =
|
nodePlacementGroupHashEntry->allowedToSeparateAnyPlacementGroup =
|
||||||
!NodeGroupHasShardPlacements(nodePlacementGroupHashEntry->nodeGroupId);
|
!NodeGroupHasDistributedTableShardPlacements(
|
||||||
|
nodePlacementGroupHashEntry->nodeGroupId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NodeToPlacementGroupHashAssignNodes assigns all active shard placements in
|
* TryAssignPlacementGroupsToNodeGroups tries to assign placements that need
|
||||||
* the cluster that need separate nodes to individual worker nodes.
|
* separate nodes within given placement list to individual worker nodes.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
NodeToPlacementGroupHashAssignNodes(HTAB *nodePlacementGroupHash,
|
TryAssignPlacementGroupsToNodeGroups(RebalancerPlacementSeparationContext *context,
|
||||||
List *activeWorkerNodeList,
|
List *activeWorkerNodeList,
|
||||||
List *rebalancePlacementList,
|
List *rebalancePlacementList,
|
||||||
FmgrInfo *shardAllowedOnNodeUDF)
|
FmgrInfo *shardAllowedOnNodeUDF)
|
||||||
|
@ -235,7 +232,7 @@ NodeToPlacementGroupHashAssignNodes(HTAB *nodePlacementGroupHash,
|
||||||
List *unassignedPlacementList = NIL;
|
List *unassignedPlacementList = NIL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Assign as much as possible shard placement groups to worker nodes where
|
* Assign as much as possible shardgroup placements to worker nodes where
|
||||||
* they are stored already.
|
* they are stored already.
|
||||||
*/
|
*/
|
||||||
ShardPlacement *shardPlacement = NULL;
|
ShardPlacement *shardPlacement = NULL;
|
||||||
|
@ -247,20 +244,20 @@ NodeToPlacementGroupHashAssignNodes(HTAB *nodePlacementGroupHash,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 shardPlacementGroupId = shardPlacement->groupId;
|
int32 currentNodeGroupId = shardPlacement->groupId;
|
||||||
if (NodeToPlacementGroupHashAssignNode(nodePlacementGroupHash,
|
if (TryAssignPlacementGroupToNodeGroup(context,
|
||||||
shardPlacementGroupId,
|
currentNodeGroupId,
|
||||||
shardPlacement,
|
shardPlacement,
|
||||||
shardAllowedOnNodeUDF))
|
shardAllowedOnNodeUDF))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* NodeToPlacementGroupHashAssignNode() succeeds for each worker node
|
* TryAssignPlacementGroupToNodeGroup() succeeds for each worker node
|
||||||
* once, hence we must not have removed the worker node from the list
|
* once, hence we must not have removed the worker node from the list
|
||||||
* yet, and WorkerNodeListGetNodeWithGroupId() ensures that already.
|
* yet, and WorkerNodeListGetNodeWithGroupId() ensures that already.
|
||||||
*/
|
*/
|
||||||
int currentPlacementNodeIdx =
|
int currentPlacementNodeIdx =
|
||||||
WorkerNodeListGetNodeWithGroupId(availableWorkerList,
|
WorkerNodeListGetNodeWithGroupId(availableWorkerList,
|
||||||
shardPlacementGroupId);
|
currentNodeGroupId);
|
||||||
availableWorkerList = list_delete_nth_cell(availableWorkerList,
|
availableWorkerList = list_delete_nth_cell(availableWorkerList,
|
||||||
currentPlacementNodeIdx);
|
currentPlacementNodeIdx);
|
||||||
}
|
}
|
||||||
|
@ -274,7 +271,7 @@ NodeToPlacementGroupHashAssignNodes(HTAB *nodePlacementGroupHash,
|
||||||
bool emitWarning = false;
|
bool emitWarning = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For the shard placement groups that could not be assigned to their
|
* For the shardgroup placements that could not be assigned to their
|
||||||
* current node, assign them to any other node that is available.
|
* current node, assign them to any other node that is available.
|
||||||
*/
|
*/
|
||||||
ShardPlacement *unassignedShardPlacement = NULL;
|
ShardPlacement *unassignedShardPlacement = NULL;
|
||||||
|
@ -285,7 +282,7 @@ NodeToPlacementGroupHashAssignNodes(HTAB *nodePlacementGroupHash,
|
||||||
WorkerNode *availableWorkerNode = NULL;
|
WorkerNode *availableWorkerNode = NULL;
|
||||||
foreach_ptr(availableWorkerNode, availableWorkerList)
|
foreach_ptr(availableWorkerNode, availableWorkerList)
|
||||||
{
|
{
|
||||||
if (NodeToPlacementGroupHashAssignNode(nodePlacementGroupHash,
|
if (TryAssignPlacementGroupToNodeGroup(context,
|
||||||
availableWorkerNode->groupId,
|
availableWorkerNode->groupId,
|
||||||
unassignedShardPlacement,
|
unassignedShardPlacement,
|
||||||
shardAllowedOnNodeUDF))
|
shardAllowedOnNodeUDF))
|
||||||
|
@ -310,24 +307,32 @@ NodeToPlacementGroupHashAssignNodes(HTAB *nodePlacementGroupHash,
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NodeToPlacementGroupHashAssignNode is an helper to
|
* TryAssignPlacementGroupToNodeGroup is an helper to
|
||||||
* NodeToPlacementGroupHashAssignNodes that tries to assign given
|
* TryAssignPlacementGroupsToNodeGroups that tries to assign given
|
||||||
* shard placement to given node and returns true if it succeeds.
|
* shard placement to given node and returns true if it succeeds.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
NodeToPlacementGroupHashAssignNode(HTAB *nodePlacementGroupHash,
|
TryAssignPlacementGroupToNodeGroup(RebalancerPlacementSeparationContext *context,
|
||||||
int32 nodeGroupId,
|
int32 candidateNodeGroupId,
|
||||||
ShardPlacement *shardPlacement,
|
ShardPlacement *shardPlacement,
|
||||||
FmgrInfo *shardAllowedOnNodeUDF)
|
FmgrInfo *shardAllowedOnNodeUDF)
|
||||||
{
|
{
|
||||||
|
HTAB *nodePlacementGroupHash = context->nodePlacementGroupHash;
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
NodeToPlacementGroupHashEntry *nodePlacementGroupHashEntry =
|
NodeToPlacementGroupHashEntry *nodePlacementGroupHashEntry =
|
||||||
NodeToPlacementGroupHashGetNodeWithGroupId(nodePlacementGroupHash, nodeGroupId);
|
hash_search(nodePlacementGroupHash, &candidateNodeGroupId, HASH_FIND, &found);
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
ereport(ERROR, (errmsg("no such node is found")));
|
||||||
|
}
|
||||||
|
|
||||||
if (nodePlacementGroupHashEntry->assignedPlacementGroup)
|
if (nodePlacementGroupHashEntry->assignedPlacementGroup)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Right now callers of this function call it once for each distinct
|
* Right now callers of this function call it once for each distinct
|
||||||
* shard placement group, hence we assume that shard placement group
|
* shardgroup placement, hence we assume that shardgroup placement
|
||||||
* that given shard placement belongs to and
|
* that given shard placement belongs to and
|
||||||
* nodePlacementGroupHashEntry->assignedPlacementGroup cannot be the
|
* nodePlacementGroupHashEntry->assignedPlacementGroup cannot be the
|
||||||
* same, without checking.
|
* same, without checking.
|
||||||
|
@ -345,7 +350,7 @@ NodeToPlacementGroupHashAssignNode(HTAB *nodePlacementGroupHash,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
WorkerNode *workerNode = PrimaryNodeForGroup(nodeGroupId, NULL);
|
WorkerNode *workerNode = PrimaryNodeForGroup(candidateNodeGroupId, NULL);
|
||||||
Datum allowed = FunctionCall2(shardAllowedOnNodeUDF, shardPlacement->shardId,
|
Datum allowed = FunctionCall2(shardAllowedOnNodeUDF, shardPlacement->shardId,
|
||||||
workerNode->nodeId);
|
workerNode->nodeId);
|
||||||
if (!DatumGetBool(allowed))
|
if (!DatumGetBool(allowed))
|
||||||
|
@ -354,7 +359,7 @@ NodeToPlacementGroupHashAssignNode(HTAB *nodePlacementGroupHash,
|
||||||
}
|
}
|
||||||
|
|
||||||
nodePlacementGroupHashEntry->assignedPlacementGroup =
|
nodePlacementGroupHashEntry->assignedPlacementGroup =
|
||||||
GetShardPlacementGroupForPlacement(shardPlacement->shardId,
|
GetShardgroupPlacementForPlacement(shardPlacement->shardId,
|
||||||
shardPlacement->placementId);
|
shardPlacement->placementId);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -362,28 +367,34 @@ NodeToPlacementGroupHashAssignNode(HTAB *nodePlacementGroupHash,
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* RebalancerPlacementIsolationContextPlacementIsAllowedOnWorker returns true
|
* RebalancerPlacementSeparationContextPlacementIsAllowedOnWorker returns true
|
||||||
* if shard placement with given shardId & placementId is allowed to be stored
|
* if shard placement with given shardId & placementId is allowed to be stored
|
||||||
* on given worker node.
|
* on given worker node.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
RebalancerPlacementIsolationContextPlacementIsAllowedOnWorker(
|
RebalancerPlacementSeparationContextPlacementIsAllowedOnWorker(
|
||||||
RebalancerPlacementIsolationContext *context,
|
RebalancerPlacementSeparationContext *context,
|
||||||
uint64 shardId,
|
uint64 shardId,
|
||||||
uint64 placementId,
|
uint64 placementId,
|
||||||
WorkerNode *workerNode)
|
WorkerNode *workerNode)
|
||||||
{
|
{
|
||||||
HTAB *nodePlacementGroupHash = context->nodePlacementGroupHash;
|
HTAB *nodePlacementGroupHash = context->nodePlacementGroupHash;
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
NodeToPlacementGroupHashEntry *nodePlacementGroupHashEntry =
|
NodeToPlacementGroupHashEntry *nodePlacementGroupHashEntry =
|
||||||
NodeToPlacementGroupHashGetNodeWithGroupId(nodePlacementGroupHash,
|
hash_search(nodePlacementGroupHash, &(workerNode->groupId), HASH_FIND, &found);
|
||||||
workerNode->groupId);
|
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
ereport(ERROR, (errmsg("no such node is found")));
|
||||||
|
}
|
||||||
|
|
||||||
ShardInterval *shardInterval = LoadShardInterval(shardId);
|
ShardInterval *shardInterval = LoadShardInterval(shardId);
|
||||||
if (!shardInterval->needsSeparateNode)
|
if (!shardInterval->needsSeparateNode)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* It doesn't need a separate node, but is the node used to separate
|
* It doesn't need a separate node, but is the node used to separate
|
||||||
* a shard placement group? If so, we cannot store it on this node.
|
* a shardgroup placement? If so, we cannot store it on this node.
|
||||||
*/
|
*/
|
||||||
return nodePlacementGroupHashEntry->shouldHaveShards &&
|
return nodePlacementGroupHashEntry->shouldHaveShards &&
|
||||||
nodePlacementGroupHashEntry->assignedPlacementGroup == NULL;
|
nodePlacementGroupHashEntry->assignedPlacementGroup == NULL;
|
||||||
|
@ -399,35 +410,13 @@ RebalancerPlacementIsolationContextPlacementIsAllowedOnWorker(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShardPlacementGroup *placementGroup =
|
ShardgroupPlacement *placementGroup =
|
||||||
GetShardPlacementGroupForPlacement(shardId, placementId);
|
GetShardgroupPlacementForPlacement(shardId, placementId);
|
||||||
return ShardPlacementGroupsSame(nodePlacementGroupHashEntry->assignedPlacementGroup,
|
return ShardgroupPlacementsSame(nodePlacementGroupHashEntry->assignedPlacementGroup,
|
||||||
placementGroup);
|
placementGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* NodeToPlacementGroupHashGetNodeWithGroupId searches given hash table for
|
|
||||||
* NodeToPlacementGroupHashEntry with given node id and returns it.
|
|
||||||
*
|
|
||||||
* Throws an error if no such entry is found.
|
|
||||||
*/
|
|
||||||
static NodeToPlacementGroupHashEntry *
|
|
||||||
NodeToPlacementGroupHashGetNodeWithGroupId(HTAB *nodePlacementGroupHash,
|
|
||||||
int32 nodeGroupId)
|
|
||||||
{
|
|
||||||
NodeToPlacementGroupHashEntry *nodePlacementGroupHashEntry =
|
|
||||||
hash_search(nodePlacementGroupHash, &nodeGroupId, HASH_FIND, NULL);
|
|
||||||
|
|
||||||
if (nodePlacementGroupHashEntry == NULL)
|
|
||||||
{
|
|
||||||
ereport(ERROR, (errmsg("no such node is found")));
|
|
||||||
}
|
|
||||||
|
|
||||||
return nodePlacementGroupHashEntry;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PlacementListGetUniqueNodeGroupIds returns a list of unique node group ids
|
* PlacementListGetUniqueNodeGroupIds returns a list of unique node group ids
|
||||||
* that are used by given list of shard placements.
|
* that are used by given list of shard placements.
|
||||||
|
@ -441,7 +430,7 @@ PlacementListGetUniqueNodeGroupIds(List *placementList)
|
||||||
foreach_ptr(shardPlacement, placementList)
|
foreach_ptr(shardPlacement, placementList)
|
||||||
{
|
{
|
||||||
placementListUniqueNodeGroupIds =
|
placementListUniqueNodeGroupIds =
|
||||||
list_append_unique_oid(placementListUniqueNodeGroupIds,
|
list_append_unique_int(placementListUniqueNodeGroupIds,
|
||||||
shardPlacement->groupId);
|
shardPlacement->groupId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
#include "distributed/pg_dist_rebalance_strategy.h"
|
#include "distributed/pg_dist_rebalance_strategy.h"
|
||||||
#include "distributed/reference_table_utils.h"
|
#include "distributed/reference_table_utils.h"
|
||||||
#include "distributed/remote_commands.h"
|
#include "distributed/remote_commands.h"
|
||||||
#include "distributed/rebalancer_placement_isolation.h"
|
#include "distributed/rebalancer_placement_separation.h"
|
||||||
#include "distributed/resource_lock.h"
|
#include "distributed/resource_lock.h"
|
||||||
#include "distributed/shard_rebalancer.h"
|
#include "distributed/shard_rebalancer.h"
|
||||||
#include "distributed/shard_cleaner.h"
|
#include "distributed/shard_cleaner.h"
|
||||||
|
@ -147,7 +147,7 @@ typedef struct RebalanceContext
|
||||||
FmgrInfo nodeCapacityUDF;
|
FmgrInfo nodeCapacityUDF;
|
||||||
FmgrInfo shardAllowedOnNodeUDF;
|
FmgrInfo shardAllowedOnNodeUDF;
|
||||||
|
|
||||||
RebalancerPlacementIsolationContext *rebalancerPlacementGroupIsolationContext;
|
RebalancerPlacementSeparationContext *shardgroupPlacementSeparationContext;
|
||||||
} RebalanceContext;
|
} RebalanceContext;
|
||||||
|
|
||||||
/* WorkerHashKey contains hostname and port to be used as a key in a hash */
|
/* WorkerHashKey contains hostname and port to be used as a key in a hash */
|
||||||
|
@ -594,8 +594,8 @@ GetRebalanceSteps(RebalanceOptions *options)
|
||||||
options->threshold = options->rebalanceStrategy->minimumThreshold;
|
options->threshold = options->rebalanceStrategy->minimumThreshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
context.rebalancerPlacementGroupIsolationContext =
|
context.shardgroupPlacementSeparationContext =
|
||||||
PrepareRebalancerPlacementIsolationContext(
|
PrepareRebalancerPlacementSeparationContext(
|
||||||
activeWorkerList,
|
activeWorkerList,
|
||||||
FlattenNestedList(activeShardPlacementListList),
|
FlattenNestedList(activeShardPlacementListList),
|
||||||
options->workerNode,
|
options->workerNode,
|
||||||
|
@ -625,8 +625,8 @@ ShardAllowedOnNode(uint64 shardId, uint64 placementId, WorkerNode *workerNode,
|
||||||
|
|
||||||
RebalanceContext *context = voidContext;
|
RebalanceContext *context = voidContext;
|
||||||
|
|
||||||
if (!RebalancerPlacementIsolationContextPlacementIsAllowedOnWorker(
|
if (!RebalancerPlacementSeparationContextPlacementIsAllowedOnWorker(
|
||||||
context->rebalancerPlacementGroupIsolationContext,
|
context->shardgroupPlacementSeparationContext,
|
||||||
shardId, placementId, workerNode))
|
shardId, placementId, workerNode))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -3190,7 +3190,7 @@ ReplicationPlacementUpdates(List *workerNodeList, List *activeShardPlacementList
|
||||||
{
|
{
|
||||||
WorkerNode *workerNode = list_nth(workerNodeList, workerNodeIndex);
|
WorkerNode *workerNode = list_nth(workerNodeList, workerNodeIndex);
|
||||||
|
|
||||||
if (!NodeCanBeUsedForNonIsolatedPlacements(workerNode))
|
if (!NodeCanBeUsedForNonSeparatedPlacements(workerNode))
|
||||||
{
|
{
|
||||||
/* never replicate placements to nodes that should not have placements */
|
/* never replicate placements to nodes that should not have placements */
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -273,22 +273,22 @@ ErrorIfCoordinatorNotAddedAsWorkerNode()
|
||||||
/*
|
/*
|
||||||
* NewDistributedTablePlacementNodeList returns a list of all active, primary
|
* NewDistributedTablePlacementNodeList returns a list of all active, primary
|
||||||
* worker nodes that can store new data, i.e shouldstoreshards is 'true'
|
* worker nodes that can store new data, i.e shouldstoreshards is 'true'
|
||||||
* and that is not used to isolate a shard placement group.
|
* and that is not used to isolate a shardgroup placement.
|
||||||
*/
|
*/
|
||||||
List *
|
List *
|
||||||
NewDistributedTablePlacementNodeList(LOCKMODE lockMode)
|
NewDistributedTablePlacementNodeList(LOCKMODE lockMode)
|
||||||
{
|
{
|
||||||
EnsureModificationsCanRun();
|
EnsureModificationsCanRun();
|
||||||
return FilterActiveNodeListFunc(lockMode, NodeCanBeUsedForNonIsolatedPlacements);
|
return FilterActiveNodeListFunc(lockMode, NodeCanBeUsedForNonSeparatedPlacements);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NodeCanBeUsedForNonIsolatedPlacements returns true if given node can be
|
* NodeCanBeUsedForNonSeparatedPlacements returns true if given node can be
|
||||||
* used to store shard placements that don't need separate nodes.
|
* used to store shard placements that don't need separate nodes.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
NodeCanBeUsedForNonIsolatedPlacements(WorkerNode *node)
|
NodeCanBeUsedForNonSeparatedPlacements(WorkerNode *node)
|
||||||
{
|
{
|
||||||
if (!NodeIsPrimary(node))
|
if (!NodeIsPrimary(node))
|
||||||
{
|
{
|
||||||
|
@ -300,7 +300,7 @@ NodeCanBeUsedForNonIsolatedPlacements(WorkerNode *node)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NodeGroupGetSeparatedShardPlacementGroup(node->groupId) == NULL;
|
return NodeGroupGetSeparatedShardgroupPlacement(node->groupId) == NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,9 @@
|
||||||
|
|
||||||
ALTER TABLE pg_dist_shard ADD COLUMN needsseparatenode boolean NOT NULL DEFAULT false;
|
ALTER TABLE pg_dist_shard ADD COLUMN needsseparatenode boolean NOT NULL DEFAULT false;
|
||||||
|
|
||||||
|
DROP FUNCTION pg_catalog.citus_internal_add_shard_metadata(regclass, bigint, "char", text, text);
|
||||||
#include "udfs/citus_internal_add_shard_metadata/12.2-1.sql"
|
#include "udfs/citus_internal_add_shard_metadata/12.2-1.sql"
|
||||||
|
|
||||||
#include "udfs/citus_internal_shard_group_set_needsseparatenode/12.2-1.sql"
|
#include "udfs/citus_internal_shard_group_set_needsseparatenode/12.2-1.sql"
|
||||||
#include "udfs/citus_shard_property_set/12.2-1.sql"
|
#include "udfs/citus_shard_property_set/12.2-1.sql"
|
||||||
|
|
||||||
|
|
|
@ -2,22 +2,11 @@
|
||||||
CREATE OR REPLACE FUNCTION pg_catalog.citus_internal_add_shard_metadata(
|
CREATE OR REPLACE FUNCTION pg_catalog.citus_internal_add_shard_metadata(
|
||||||
relation_id regclass, shard_id bigint,
|
relation_id regclass, shard_id bigint,
|
||||||
storage_type "char", shard_min_value text,
|
storage_type "char", shard_min_value text,
|
||||||
shard_max_value text, needs_separate_node boolean
|
shard_max_value text,
|
||||||
|
needs_separate_node boolean default false
|
||||||
)
|
)
|
||||||
RETURNS void
|
RETURNS void
|
||||||
LANGUAGE C
|
LANGUAGE C
|
||||||
AS 'MODULE_PATHNAME', $$citus_internal_add_shard_metadata$$;
|
AS 'MODULE_PATHNAME', $$citus_internal_add_shard_metadata$$;
|
||||||
COMMENT ON FUNCTION pg_catalog.citus_internal_add_shard_metadata(regclass, bigint, "char", text, text, boolean) IS
|
COMMENT ON FUNCTION pg_catalog.citus_internal_add_shard_metadata(regclass, bigint, "char", text, text, boolean) IS
|
||||||
'Inserts into pg_dist_shard with user checks';
|
'Inserts into pg_dist_shard with user checks';
|
||||||
|
|
||||||
-- replace the old one so it would call the old C function without needs_separate_node
|
|
||||||
CREATE OR REPLACE FUNCTION pg_catalog.citus_internal_add_shard_metadata(
|
|
||||||
relation_id regclass, shard_id bigint,
|
|
||||||
storage_type "char", shard_min_value text,
|
|
||||||
shard_max_value text
|
|
||||||
)
|
|
||||||
RETURNS void
|
|
||||||
LANGUAGE C
|
|
||||||
AS 'MODULE_PATHNAME', $$citus_internal_add_shard_metadata_legacy$$;
|
|
||||||
COMMENT ON FUNCTION pg_catalog.citus_internal_add_shard_metadata(regclass, bigint, "char", text, text) IS
|
|
||||||
'Inserts into pg_dist_shard with user checks';
|
|
||||||
|
|
|
@ -2,22 +2,11 @@
|
||||||
CREATE OR REPLACE FUNCTION pg_catalog.citus_internal_add_shard_metadata(
|
CREATE OR REPLACE FUNCTION pg_catalog.citus_internal_add_shard_metadata(
|
||||||
relation_id regclass, shard_id bigint,
|
relation_id regclass, shard_id bigint,
|
||||||
storage_type "char", shard_min_value text,
|
storage_type "char", shard_min_value text,
|
||||||
shard_max_value text, needs_separate_node boolean
|
shard_max_value text,
|
||||||
|
needs_separate_node boolean default false
|
||||||
)
|
)
|
||||||
RETURNS void
|
RETURNS void
|
||||||
LANGUAGE C
|
LANGUAGE C
|
||||||
AS 'MODULE_PATHNAME', $$citus_internal_add_shard_metadata$$;
|
AS 'MODULE_PATHNAME', $$citus_internal_add_shard_metadata$$;
|
||||||
COMMENT ON FUNCTION pg_catalog.citus_internal_add_shard_metadata(regclass, bigint, "char", text, text, boolean) IS
|
COMMENT ON FUNCTION pg_catalog.citus_internal_add_shard_metadata(regclass, bigint, "char", text, text, boolean) IS
|
||||||
'Inserts into pg_dist_shard with user checks';
|
'Inserts into pg_dist_shard with user checks';
|
||||||
|
|
||||||
-- replace the old one so it would call the old C function without needs_separate_node
|
|
||||||
CREATE OR REPLACE FUNCTION pg_catalog.citus_internal_add_shard_metadata(
|
|
||||||
relation_id regclass, shard_id bigint,
|
|
||||||
storage_type "char", shard_min_value text,
|
|
||||||
shard_max_value text
|
|
||||||
)
|
|
||||||
RETURNS void
|
|
||||||
LANGUAGE C
|
|
||||||
AS 'MODULE_PATHNAME', $$citus_internal_add_shard_metadata_legacy$$;
|
|
||||||
COMMENT ON FUNCTION pg_catalog.citus_internal_add_shard_metadata(regclass, bigint, "char", text, text) IS
|
|
||||||
'Inserts into pg_dist_shard with user checks';
|
|
||||||
|
|
|
@ -109,7 +109,7 @@ typedef struct
|
||||||
uint32 colocatationId;
|
uint32 colocatationId;
|
||||||
int shardIntervalIndex;
|
int shardIntervalIndex;
|
||||||
int32 nodeGroupId;
|
int32 nodeGroupId;
|
||||||
} ShardPlacementGroup;
|
} ShardgroupPlacement;
|
||||||
|
|
||||||
|
|
||||||
typedef enum CascadeToColocatedOption
|
typedef enum CascadeToColocatedOption
|
||||||
|
@ -331,11 +331,12 @@ extern int ShardIntervalCount(Oid relationId);
|
||||||
extern List * LoadShardList(Oid relationId);
|
extern List * LoadShardList(Oid relationId);
|
||||||
extern ShardInterval * CopyShardInterval(ShardInterval *srcInterval);
|
extern ShardInterval * CopyShardInterval(ShardInterval *srcInterval);
|
||||||
extern uint64 ShardLength(uint64 shardId);
|
extern uint64 ShardLength(uint64 shardId);
|
||||||
extern ShardPlacementGroup * NodeGroupGetSeparatedShardPlacementGroup(int32 groupId);
|
extern ShardgroupPlacement * NodeGroupGetSeparatedShardgroupPlacement(int32 groupId);
|
||||||
extern bool ShardPlacementGroupsSame(const ShardPlacementGroup *leftGroup,
|
extern bool ShardgroupPlacementsSame(const ShardgroupPlacement *leftGroup,
|
||||||
const ShardPlacementGroup *rightGroup);
|
const ShardgroupPlacement *rightGroup);
|
||||||
extern bool NodeGroupHasShardPlacements(int32 groupId);
|
extern bool NodeGroupHasShardPlacements(int32 groupId);
|
||||||
extern ShardPlacementGroup * GetShardPlacementGroupForPlacement(uint64 shardId,
|
extern bool NodeGroupHasDistributedTableShardPlacements(int32 groupId);
|
||||||
|
extern ShardgroupPlacement * GetShardgroupPlacementForPlacement(uint64 shardId,
|
||||||
uint64 placementId);
|
uint64 placementId);
|
||||||
extern bool IsActiveShardPlacement(ShardPlacement *ShardPlacement);
|
extern bool IsActiveShardPlacement(ShardPlacement *ShardPlacement);
|
||||||
extern bool IsRemoteShardPlacement(ShardPlacement *shardPlacement);
|
extern bool IsRemoteShardPlacement(ShardPlacement *shardPlacement);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*-------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* rebalancer_placement_isolation.h
|
* rebalancer_placement_separation.h
|
||||||
* Routines to determine which worker node should be used to separate
|
* Routines to determine which worker node should be used to separate
|
||||||
* a colocated set of shard placements that need separate nodes.
|
* a colocated set of shard placements that need separate nodes.
|
||||||
*
|
*
|
||||||
|
@ -18,10 +18,10 @@
|
||||||
|
|
||||||
#include "distributed/metadata_utility.h"
|
#include "distributed/metadata_utility.h"
|
||||||
|
|
||||||
struct RebalancerPlacementIsolationContext;
|
struct RebalancerPlacementSeparationContext;
|
||||||
typedef struct RebalancerPlacementIsolationContext RebalancerPlacementIsolationContext;
|
typedef struct RebalancerPlacementSeparationContext RebalancerPlacementSeparationContext;
|
||||||
|
|
||||||
extern RebalancerPlacementIsolationContext * PrepareRebalancerPlacementIsolationContext(
|
extern RebalancerPlacementSeparationContext * PrepareRebalancerPlacementSeparationContext(
|
||||||
List *activeWorkerNodeList,
|
List *activeWorkerNodeList,
|
||||||
List
|
List
|
||||||
*
|
*
|
||||||
|
@ -32,8 +32,8 @@ extern RebalancerPlacementIsolationContext * PrepareRebalancerPlacementIsolation
|
||||||
FmgrInfo
|
FmgrInfo
|
||||||
*
|
*
|
||||||
shardAllowedOnNodeUDF);
|
shardAllowedOnNodeUDF);
|
||||||
extern bool RebalancerPlacementIsolationContextPlacementIsAllowedOnWorker(
|
extern bool RebalancerPlacementSeparationContextPlacementIsAllowedOnWorker(
|
||||||
RebalancerPlacementIsolationContext *context,
|
RebalancerPlacementSeparationContext *context,
|
||||||
uint64 shardId,
|
uint64 shardId,
|
||||||
uint64
|
uint64
|
||||||
placementId,
|
placementId,
|
|
@ -78,7 +78,7 @@ extern List * ReferenceTablePlacementNodeList(LOCKMODE lockMode);
|
||||||
extern WorkerNode * CoordinatorNodeIfAddedAsWorkerOrError(void);
|
extern WorkerNode * CoordinatorNodeIfAddedAsWorkerOrError(void);
|
||||||
extern void ErrorIfCoordinatorNotAddedAsWorkerNode(void);
|
extern void ErrorIfCoordinatorNotAddedAsWorkerNode(void);
|
||||||
extern List * NewDistributedTablePlacementNodeList(LOCKMODE lockMode);
|
extern List * NewDistributedTablePlacementNodeList(LOCKMODE lockMode);
|
||||||
extern bool NodeCanBeUsedForNonIsolatedPlacements(WorkerNode *node);
|
extern bool NodeCanBeUsedForNonSeparatedPlacements(WorkerNode *node);
|
||||||
extern List * ActiveReadableNonCoordinatorNodeList(void);
|
extern List * ActiveReadableNonCoordinatorNodeList(void);
|
||||||
extern List * ActiveReadableNodeList(void);
|
extern List * ActiveReadableNodeList(void);
|
||||||
extern WorkerNode * FindWorkerNode(const char *nodeName, int32 nodePort);
|
extern WorkerNode * FindWorkerNode(const char *nodeName, int32 nodePort);
|
||||||
|
|
|
@ -812,14 +812,14 @@ ORDER BY result;
|
||||||
SELECT citus_shard_property_set(NULL, anti_affinity=>true);
|
SELECT citus_shard_property_set(NULL, anti_affinity=>true);
|
||||||
ERROR: shard_id cannot be NULL
|
ERROR: shard_id cannot be NULL
|
||||||
SELECT citus_shard_property_set(0, anti_affinity=>true);
|
SELECT citus_shard_property_set(0, anti_affinity=>true);
|
||||||
ERROR: shard xxxxx does not exist
|
ERROR: could not find valid entry for shard xxxxx
|
||||||
SELECT citus_shard_property_set(NULL, anti_affinity=>false);
|
SELECT citus_shard_property_set(NULL, anti_affinity=>false);
|
||||||
ERROR: shard_id cannot be NULL
|
ERROR: shard_id cannot be NULL
|
||||||
SELECT citus_shard_property_set(0, anti_affinity=>false);
|
SELECT citus_shard_property_set(0, anti_affinity=>false);
|
||||||
ERROR: shard xxxxx does not exist
|
ERROR: could not find valid entry for shard xxxxx
|
||||||
-- we verify whether shard exists even if anti_affinity is not provided
|
-- we verify whether shard exists even if anti_affinity is not provided
|
||||||
SELECT citus_shard_property_set(0, anti_affinity=>NULL);
|
SELECT citus_shard_property_set(0, anti_affinity=>NULL);
|
||||||
ERROR: shard xxxxx does not exist
|
ERROR: could not find valid entry for shard xxxxx
|
||||||
CREATE TABLE append_table (a int, b int);
|
CREATE TABLE append_table (a int, b int);
|
||||||
SELECT create_distributed_table('append_table', 'a', 'append');
|
SELECT create_distributed_table('append_table', 'a', 'append');
|
||||||
create_distributed_table
|
create_distributed_table
|
||||||
|
@ -858,21 +858,21 @@ SELECT citus_add_local_table_to_metadata('local_table');
|
||||||
|
|
||||||
-- all should fail
|
-- all should fail
|
||||||
SELECT citus_shard_property_set(shardid, anti_affinity=>true) FROM pg_dist_shard WHERE logicalrelid = 'append_table'::regclass LIMIT 1;
|
SELECT citus_shard_property_set(shardid, anti_affinity=>true) FROM pg_dist_shard WHERE logicalrelid = 'append_table'::regclass LIMIT 1;
|
||||||
ERROR: shard isolation is only supported for hash distributed tables
|
ERROR: setting anti-affinity property is only supported for hash distributed tables
|
||||||
SELECT citus_shard_property_set(shardid, anti_affinity=>true) FROM pg_dist_shard WHERE logicalrelid = 'range_table'::regclass LIMIT 1;
|
SELECT citus_shard_property_set(shardid, anti_affinity=>true) FROM pg_dist_shard WHERE logicalrelid = 'range_table'::regclass LIMIT 1;
|
||||||
ERROR: shard isolation is only supported for hash distributed tables
|
ERROR: setting anti-affinity property is only supported for hash distributed tables
|
||||||
SELECT citus_shard_property_set(shardid, anti_affinity=>true) FROM pg_dist_shard WHERE logicalrelid = 'ref_table'::regclass LIMIT 1;
|
SELECT citus_shard_property_set(shardid, anti_affinity=>true) FROM pg_dist_shard WHERE logicalrelid = 'ref_table'::regclass LIMIT 1;
|
||||||
ERROR: shard isolation is only supported for hash distributed tables
|
ERROR: setting anti-affinity property is only supported for hash distributed tables
|
||||||
SELECT citus_shard_property_set(shardid, anti_affinity=>true) FROM pg_dist_shard WHERE logicalrelid = 'local_table'::regclass LIMIT 1;
|
SELECT citus_shard_property_set(shardid, anti_affinity=>true) FROM pg_dist_shard WHERE logicalrelid = 'local_table'::regclass LIMIT 1;
|
||||||
ERROR: shard isolation is only supported for hash distributed tables
|
ERROR: setting anti-affinity property is only supported for hash distributed tables
|
||||||
SELECT citus_shard_property_set(shardid, anti_affinity=>false) FROM pg_dist_shard WHERE logicalrelid = 'append_table'::regclass LIMIT 1;
|
SELECT citus_shard_property_set(shardid, anti_affinity=>false) FROM pg_dist_shard WHERE logicalrelid = 'append_table'::regclass LIMIT 1;
|
||||||
ERROR: shard isolation is only supported for hash distributed tables
|
ERROR: setting anti-affinity property is only supported for hash distributed tables
|
||||||
SELECT citus_shard_property_set(shardid, anti_affinity=>false) FROM pg_dist_shard WHERE logicalrelid = 'range_table'::regclass LIMIT 1;
|
SELECT citus_shard_property_set(shardid, anti_affinity=>false) FROM pg_dist_shard WHERE logicalrelid = 'range_table'::regclass LIMIT 1;
|
||||||
ERROR: shard isolation is only supported for hash distributed tables
|
ERROR: setting anti-affinity property is only supported for hash distributed tables
|
||||||
SELECT citus_shard_property_set(shardid, anti_affinity=>false) FROM pg_dist_shard WHERE logicalrelid = 'ref_table'::regclass LIMIT 1;
|
SELECT citus_shard_property_set(shardid, anti_affinity=>false) FROM pg_dist_shard WHERE logicalrelid = 'ref_table'::regclass LIMIT 1;
|
||||||
ERROR: shard isolation is only supported for hash distributed tables
|
ERROR: setting anti-affinity property is only supported for hash distributed tables
|
||||||
SELECT citus_shard_property_set(shardid, anti_affinity=>false) FROM pg_dist_shard WHERE logicalrelid = 'local_table'::regclass LIMIT 1;
|
SELECT citus_shard_property_set(shardid, anti_affinity=>false) FROM pg_dist_shard WHERE logicalrelid = 'local_table'::regclass LIMIT 1;
|
||||||
ERROR: shard isolation is only supported for hash distributed tables
|
ERROR: setting anti-affinity property is only supported for hash distributed tables
|
||||||
DROP TABLE range_table;
|
DROP TABLE range_table;
|
||||||
DROP TYPE composite_key_type;
|
DROP TYPE composite_key_type;
|
||||||
SET client_min_messages TO WARNING;
|
SET client_min_messages TO WARNING;
|
||||||
|
|
|
@ -173,7 +173,7 @@ step s1_set-shard-property:
|
||||||
FROM pg_dist_shard WHERE logicalrelid = 'table_to_distribute'::regclass
|
FROM pg_dist_shard WHERE logicalrelid = 'table_to_distribute'::regclass
|
||||||
ORDER BY shardid LIMIT 1;
|
ORDER BY shardid LIMIT 1;
|
||||||
|
|
||||||
ERROR: could not acquire the lock required to set anti affinity property for a shard of public.table_to_distribute
|
ERROR: could not acquire the lock required to set a property for a shard of public.table_to_distribute
|
||||||
step s1-rollback:
|
step s1-rollback:
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue