mirror of https://github.com/citusdata/citus.git
Fix distributed deadlock for TRUNCATE
parent
036b4216a8
commit
6be1bacddd
|
@ -48,32 +48,9 @@ static void AcquireDistributedLockOnRelations(List *relationIdList, LOCKMODE loc
|
||||||
void
|
void
|
||||||
ProcessTruncateStatement(TruncateStmt *truncateStatement)
|
ProcessTruncateStatement(TruncateStmt *truncateStatement)
|
||||||
{
|
{
|
||||||
ListCell *rangeVarCell = NULL;
|
|
||||||
ListCell *relationCell = NULL;
|
|
||||||
List *lockedRelations = NIL;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Lock relations while calling next three functions, because they expect
|
|
||||||
* relations to be locked. We release them then to avoid distributed
|
|
||||||
* deadlock in MX.
|
|
||||||
*/
|
|
||||||
foreach(rangeVarCell, truncateStatement->relations)
|
|
||||||
{
|
|
||||||
RangeVar *rangeVar = (RangeVar *) lfirst(rangeVarCell);
|
|
||||||
Relation relation = heap_openrv(rangeVar, AccessShareLock);
|
|
||||||
lockedRelations = lappend(lockedRelations, relation);
|
|
||||||
}
|
|
||||||
|
|
||||||
ErrorIfUnsupportedTruncateStmt(truncateStatement);
|
ErrorIfUnsupportedTruncateStmt(truncateStatement);
|
||||||
EnsurePartitionTableNotReplicatedForTruncate(truncateStatement);
|
EnsurePartitionTableNotReplicatedForTruncate(truncateStatement);
|
||||||
ExecuteTruncateStmtSequentialIfNecessary(truncateStatement);
|
ExecuteTruncateStmtSequentialIfNecessary(truncateStatement);
|
||||||
|
|
||||||
foreach(relationCell, lockedRelations)
|
|
||||||
{
|
|
||||||
Relation relation = (Relation) lfirst(relationCell);
|
|
||||||
heap_close(relation, AccessShareLock);
|
|
||||||
}
|
|
||||||
|
|
||||||
LockTruncatedRelationMetadataInWorkers(truncateStatement);
|
LockTruncatedRelationMetadataInWorkers(truncateStatement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include "lib/stringinfo.h"
|
#include "lib/stringinfo.h"
|
||||||
#include "nodes/pg_list.h"
|
#include "nodes/pg_list.h"
|
||||||
#include "storage/lock.h"
|
#include "storage/lock.h"
|
||||||
|
#include "storage/lmgr.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
#include "utils/elog.h"
|
#include "utils/elog.h"
|
||||||
#include "utils/errcodes.h"
|
#include "utils/errcodes.h"
|
||||||
|
@ -231,6 +232,9 @@ RepairShardPlacement(int64 shardId, char *sourceNodeName, int32 sourceNodePort,
|
||||||
List *placementList = NIL;
|
List *placementList = NIL;
|
||||||
ShardPlacement *placement = NULL;
|
ShardPlacement *placement = NULL;
|
||||||
|
|
||||||
|
/* prevent table from being dropped */
|
||||||
|
LockRelationOid(distributedTableId, AccessShareLock);
|
||||||
|
|
||||||
EnsureTableOwner(distributedTableId);
|
EnsureTableOwner(distributedTableId);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "distributed/shardinterval_utils.h"
|
#include "distributed/shardinterval_utils.h"
|
||||||
#include "lib/stringinfo.h"
|
#include "lib/stringinfo.h"
|
||||||
#include "nodes/pg_list.h"
|
#include "nodes/pg_list.h"
|
||||||
|
#include "pgstat.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
#include "utils/fmgroids.h"
|
#include "utils/fmgroids.h"
|
||||||
#include "utils/lsyscache.h"
|
#include "utils/lsyscache.h"
|
||||||
|
@ -32,6 +33,7 @@
|
||||||
|
|
||||||
|
|
||||||
static char * PartitionBound(Oid partitionId);
|
static char * PartitionBound(Oid partitionId);
|
||||||
|
static Relation try_relation_open_nolock(Oid relationId);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -69,7 +71,7 @@ PartitionedTable(Oid relationId)
|
||||||
bool
|
bool
|
||||||
PartitionedTableNoLock(Oid relationId)
|
PartitionedTableNoLock(Oid relationId)
|
||||||
{
|
{
|
||||||
Relation rel = try_relation_open(relationId, NoLock);
|
Relation rel = try_relation_open_nolock(relationId);
|
||||||
bool partitionedTable = false;
|
bool partitionedTable = false;
|
||||||
|
|
||||||
/* don't error out for tables that are dropped */
|
/* don't error out for tables that are dropped */
|
||||||
|
@ -122,7 +124,7 @@ PartitionTable(Oid relationId)
|
||||||
bool
|
bool
|
||||||
PartitionTableNoLock(Oid relationId)
|
PartitionTableNoLock(Oid relationId)
|
||||||
{
|
{
|
||||||
Relation rel = try_relation_open(relationId, NoLock);
|
Relation rel = try_relation_open_nolock(relationId);
|
||||||
bool partitionTable = false;
|
bool partitionTable = false;
|
||||||
|
|
||||||
/* don't error out for tables that are dropped */
|
/* don't error out for tables that are dropped */
|
||||||
|
@ -140,6 +142,39 @@ PartitionTableNoLock(Oid relationId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* try_relation_open_nolock opens a relation with given relationId without
|
||||||
|
* acquiring locks. PostgreSQL's try_relation_open() asserts that caller
|
||||||
|
* has already acquired a lock on the relation, which we don't always do.
|
||||||
|
*
|
||||||
|
* ATTENTION:
|
||||||
|
* 1. Sync this with try_relation_open(). It hasn't changed for 10 to 12
|
||||||
|
* releases though.
|
||||||
|
* 2. We should remove this after we fix the locking/distributed deadlock
|
||||||
|
* issues with MX Truncate. See https://github.com/citusdata/citus/pull/2894
|
||||||
|
* for more discussion.
|
||||||
|
*/
|
||||||
|
static Relation
|
||||||
|
try_relation_open_nolock(Oid relationId)
|
||||||
|
{
|
||||||
|
Relation relation = NULL;
|
||||||
|
if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(relationId)))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
relation = RelationIdGetRelation(relationId);
|
||||||
|
if (!RelationIsValid(relation))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pgstat_initstats(relation);
|
||||||
|
|
||||||
|
return relation;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IsChildTable returns true if the table is inherited. Note that
|
* IsChildTable returns true if the table is inherited. Note that
|
||||||
* partition tables inherites by default. However, this function
|
* partition tables inherites by default. However, this function
|
||||||
|
|
Loading…
Reference in New Issue