From 723ea1f2c13388bf1a6afcb54aad1569441989e1 Mon Sep 17 00:00:00 2001 From: morningman Date: Sun, 20 Jul 2025 23:00:49 -0700 Subject: [PATCH] branch-3.0: [fix](catalog) fix deadlock of catalog and database(#53626) --- .../doris/datasource/ExternalDatabase.java | 86 ++++++++++--------- 1 file changed, 46 insertions(+), 40 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalDatabase.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalDatabase.java index 9b726e6b1de257..c122c8c568f82b 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalDatabase.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalDatabase.java @@ -155,50 +155,56 @@ public boolean isInitialized() { return initialized; } - public final synchronized void makeSureInitialized() { - if (isInitializing) { - return; - } - isInitializing = true; - try { - extCatalog.makeSureInitialized(); - if (!initialized) { - if (extCatalog.getUseMetaCache().get()) { - if (metaCache == null) { - metaCache = Env.getCurrentEnv().getExtMetaCacheMgr().buildMetaCache( - name, - OptionalLong.of(86400L), - OptionalLong.of(Config.external_cache_expire_time_minutes_after_access * 60L), - Config.max_meta_object_cache_num, - ignored -> listTableNames(), - localTableName -> Optional.ofNullable( - buildTableForInit(null, localTableName, - Util.genIdByName(extCatalog.getName(), name, localTableName), - extCatalog, - this, true)), - (key, value, cause) -> value.ifPresent(ExternalTable::unsetObjectCreated)); - } - setLastUpdateTime(System.currentTimeMillis()); - } else { - if (!Env.getCurrentEnv().isMaster()) { - // Forward to master and wait the journal to replay. - int waitTimeOut = ConnectContext.get() == null ? 300 : ConnectContext.get().getExecTimeout(); - MasterCatalogExecutor remoteExecutor = new MasterCatalogExecutor(waitTimeOut * 1000); - try { - remoteExecutor.forward(extCatalog.getId(), id); - } catch (Exception e) { - Util.logAndThrowRuntimeException(LOG, - String.format("failed to forward init external db %s operation to master", name), - e); + public final void makeSureInitialized() { + // Must call this method before any operation on the database to avoid deadlock of synchronized block + extCatalog.makeSureInitialized(); + synchronized (this) { + if (isInitializing) { + return; + } + isInitializing = true; + try { + if (!initialized) { + if (extCatalog.getUseMetaCache().get()) { + if (metaCache == null) { + metaCache = Env.getCurrentEnv().getExtMetaCacheMgr().buildMetaCache( + name, + OptionalLong.of(86400L), + OptionalLong.of(Config.external_cache_expire_time_minutes_after_access * 60L), + Config.max_meta_object_cache_num, + ignored -> listTableNames(), + localTableName -> Optional.ofNullable( + buildTableForInit(null, localTableName, + Util.genIdByName(extCatalog.getName(), name, localTableName), + extCatalog, + this, true)), + (key, value, cause) + -> value.ifPresent(ExternalTable::unsetObjectCreated)); + } + setLastUpdateTime(System.currentTimeMillis()); + } else { + if (!Env.getCurrentEnv().isMaster()) { + // Forward to master and wait the journal to replay. + int waitTimeOut = ConnectContext.get() == null ? 300 + : ConnectContext.get().getExecTimeout(); + MasterCatalogExecutor remoteExecutor = new MasterCatalogExecutor(waitTimeOut * 1000); + try { + remoteExecutor.forward(extCatalog.getId(), id); + } catch (Exception e) { + Util.logAndThrowRuntimeException(LOG, + String.format("failed to forward init external db %s operation to master", + name), + e); + } + return; } - return; + init(); } - init(); + initialized = true; } - initialized = true; + } finally { + isInitializing = false; } - } finally { - isInitializing = false; } }