failure-handling-drop-db
Onur Tirtir 2024-02-20 18:57:50 +03:00
parent 62857d59ab
commit 2f12dd179c
4 changed files with 83 additions and 43 deletions

View File

@ -632,13 +632,11 @@ List *
PreprocessDropDatabaseStmt(Node *node, const char *queryString,
ProcessUtilityContext processUtilityContext)
{
if (!EnableCreateDatabasePropagation || !ShouldPropagate())
if (!IsDistributedDropDatabaseCommand(node))
{
return NIL;
}
EnsurePropagationToCoordinator();
DropdbStmt *stmt = (DropdbStmt *) node;
bool isPostProcess = false;
@ -657,22 +655,78 @@ PreprocessDropDatabaseStmt(Node *node, const char *queryString,
return NIL;
}
EnsurePropagationToCoordinator();
SerializeDistributedDDLsOnObjectClassObject(OCLASS_DATABASE, stmt->dbname);
char *dropDatabaseCommand = DeparseTreeNode(node);
OperationId operationId = RegisterOperationNeedingCleanup();
List *dropDatabaseCommands = list_make3(DISABLE_DDL_PROPAGATION,
(void *) dropDatabaseCommand,
char *tempDatabaseName = psprintf(TEMP_DATABASE_NAME_FMT,
operationId, GetLocalGroupId());
UnmarkObjectDistributed(linitial(addresses));
char *unmarkObjectDistributedCommand =
psprintf("SELECT pg_catalog.citus_unmark_object_distributed("
"(SELECT oid FROM pg_class WHERE relname = 'pg_database'), "
"(SELECT oid FROM pg_database WHERE datname = %s), "
"0);",
quote_literal_cstr(tempDatabaseName));
List *unmarkObjectDistributedCommands = list_make1(unmarkObjectDistributedCommand);
List *unmarkObjectDistributedDDLJobList =
NodeDDLTaskList(REMOTE_NODES, unmarkObjectDistributedCommands);
char *renameDatabaseCommand =
psprintf("ALTER DATABASE %s RENAME TO %s",
quote_identifier(stmt->dbname),
quote_identifier(tempDatabaseName));
int saveNestLevel = NewGUCNestLevel();
set_config_option("citus.enable_ddl_propagation", "off",
(superuser() ? PGC_SUSET : PGC_USERSET), PGC_S_SESSION,
GUC_ACTION_LOCAL, true, 0, false);
ExecuteUtilityCommand(renameDatabaseCommand);
AtEOXact_GUC(true, saveNestLevel);
List *renameDatabaseCommands = list_make3(DISABLE_DDL_PROPAGATION,
renameDatabaseCommand,
ENABLE_DDL_PROPAGATION);
/*
* Due to same reason stated in PostprocessCreateDatabaseStmt(), we need to
* use NontransactionalNodeDDLTaskList() to send the DROP DATABASE statement
* to the workers.
*/
List *dropDatabaseDDLJobList =
NontransactionalNodeDDLTaskList(REMOTE_NODES, dropDatabaseCommands);
return dropDatabaseDDLJobList;
List *renameDatabaseDDLJobList =
NodeDDLTaskList(REMOTE_NODES, renameDatabaseCommands);
List *allNodes = TargetWorkerSetNodeList(ALL_SHARD_NODES, RowShareLock);
WorkerNode *workerNode = NULL;
foreach_ptr(workerNode, allNodes)
{
InsertCleanupRecordInCurrentTransaction(
CLEANUP_OBJECT_DATABASE,
pstrdup(quote_identifier(tempDatabaseName)),
workerNode->groupId,
CLEANUP_DEFERRED_ON_SUCCESS
);
}
return list_concat(renameDatabaseDDLJobList, unmarkObjectDistributedDDLJobList);
}
bool
IsDistributedDropDatabaseCommand(Node *node)
{
if (!IsA(node, DropdbStmt))
{
return false;
}
if (!EnableCreateDatabasePropagation || !ShouldPropagate())
{
return false;
}
return true;
}

View File

@ -115,6 +115,7 @@ static void citus_ProcessUtilityInternal(PlannedStmt *pstmt,
struct QueryEnvironment *queryEnv,
DestReceiver *dest,
QueryCompletion *completionTag);
static bool ShouldSkipPrevProcessUtility(Node *node);
static void set_indexsafe_procflags(void);
static char * CurrentSearchPath(void);
static void IncrementUtilityHookCountersIfNecessary(Node *parsetree);
@ -785,8 +786,11 @@ citus_ProcessUtilityInternal(PlannedStmt *pstmt,
PreprocessAlterExtensionCitusStmtForCitusColumnar(parsetree);
}
if (!ShouldSkipPrevProcessUtility(parsetree))
{
PrevProcessUtility(pstmt, queryString, false, context,
params, queryEnv, dest, completionTag);
}
if (isAlterExtensionUpdateCitusStmt)
{
@ -947,6 +951,13 @@ citus_ProcessUtilityInternal(PlannedStmt *pstmt,
}
static bool
ShouldSkipPrevProcessUtility(Node *node)
{
return IsDistributedDropDatabaseCommand(node);
}
/*
* UndistributeDisconnectedCitusLocalTables undistributes citus local tables that
* are not connected to any reference tables via their individual foreign key

View File

@ -119,19 +119,6 @@ citus_unmark_object_distributed(PG_FUNCTION_ARGS)
PG_RETURN_VOID();
}
if (ObjectExists(&address))
{
ereport(ERROR, (errmsg("object still exists"),
errdetail("the %s \"%s\" still exists",
getObjectTypeDescription(&address,
/* missingOk: */ false),
getObjectIdentity(&address,
/* missingOk: */ false)),
errhint("drop the object via a DROP command")));
}
UnmarkObjectDistributed(&address);
PG_RETURN_VOID();
@ -457,19 +444,6 @@ UnmarkNodeWideObjectsDistributed(Node *node)
UnmarkRolesDistributed(distributedDropRoles);
}
}
else if (IsA(node, DropdbStmt))
{
DropdbStmt *stmt = castNode(DropdbStmt, node);
char *dbName = stmt->dbname;
Oid dbOid = get_database_oid(dbName, stmt->missing_ok);
ObjectAddress *dbObjectAddress = palloc0(sizeof(ObjectAddress));
ObjectAddressSet(*dbObjectAddress, DatabaseRelationId, dbOid);
if (IsAnyObjectDistributed(list_make1(dbObjectAddress)))
{
UnmarkObjectDistributed(dbObjectAddress);
}
}
}

View File

@ -241,6 +241,7 @@ extern List * PreprocessCreateDatabaseStmt(Node *node, const char *queryString,
extern List * PostprocessCreateDatabaseStmt(Node *node, const char *queryString);
extern List * PreprocessDropDatabaseStmt(Node *node, const char *queryString,
ProcessUtilityContext processUtilityContext);
extern bool IsDistributedDropDatabaseCommand(Node *node);
extern List * DropDatabaseStmtObjectAddress(Node *node, bool missingOk,
bool isPostprocess);
extern List * CreateDatabaseStmtObjectAddress(Node *node, bool missingOk,