From c791e114072416778f909d8c136e9eca7babc213 Mon Sep 17 00:00:00 2001 From: morningman Date: Sun, 20 Jul 2025 22:55:13 -0700 Subject: [PATCH] [fix](catalog) fix deadlock of catalog and database --- .../doris/datasource/ExternalDatabase.java | 66 ++++++++++--------- 1 file changed, 35 insertions(+), 31 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 c440f481034d84..0f453b1b325ce5 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 @@ -154,41 +154,45 @@ public boolean isInitialized() { return initialized; } - public final synchronized void makeSureInitialized() { - if (isInitializing) { - return; - } - isInitializing = true; - try { - extCatalog.makeSureInitialized(); - if (!initialized) { - if (extCatalog.getUseMetaCache().get()) { - buildMetaCache(); - 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().getExecTimeoutS(); - 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()) { + buildMetaCache(); + 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().getExecTimeoutS(); + 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; + } catch (Exception e) { + LOG.warn("failed to init db {}, id {}, isInitializing: {}, initialized: {}", + this.name, this.id, isInitializing, initialized, e); + initialized = false; + } finally { + isInitializing = false; } - } catch (Exception e) { - LOG.warn("failed to init db {}, id {}, isInitializing: {}, initialized: {}", - this.name, this.id, isInitializing, initialized, e); - initialized = false; - } finally { - isInitializing = false; } }