From 29f35ebbef96650abd5ff49c16c35f14c99a3fd3 Mon Sep 17 00:00:00 2001 From: Vikram Ahuja Date: Wed, 27 May 2026 14:35:53 +0530 Subject: [PATCH] HIVE-29632: hive.fetch.task.caching=true (default) causes unbounded heap allocation thus crashing HiveServer2 with OutOfMemoryError --- .../java/org/apache/hadoop/hive/cli/CliDriver.java | 4 +++- .../hive/ql/optimizer/SimpleFetchOptimizer.java | 12 ++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/cli/src/java/org/apache/hadoop/hive/cli/CliDriver.java b/cli/src/java/org/apache/hadoop/hive/cli/CliDriver.java index 2ac3d425b704..07b063b28ff8 100644 --- a/cli/src/java/org/apache/hadoop/hive/cli/CliDriver.java +++ b/cli/src/java/org/apache/hadoop/hive/cli/CliDriver.java @@ -295,7 +295,9 @@ CommandProcessorResponse processLocalCmd(String cmd, CommandProcessor proc, CliS console.printError("Failed with exception " + e.getClass().getName() + ":" + e.getMessage(), "\n" + org.apache.hadoop.util.StringUtils.stringifyException(e)); throw new CommandProcessorException(1); - } finally { + } catch (RuntimeException e) { + throw new CommandProcessorException(1); + } finally { qp.close(); ShimLoader.getHadoopShims() .setHadoopSessionContext(String.format(USER_ID, ss.getSessionId(), ss.getUserName())); diff --git a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/SimpleFetchOptimizer.java b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/SimpleFetchOptimizer.java index e469f679faa2..aaabc602fc8a 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/SimpleFetchOptimizer.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/SimpleFetchOptimizer.java @@ -60,6 +60,7 @@ import org.apache.hadoop.hive.ql.exec.TaskFactory; import org.apache.hadoop.hive.ql.exec.Utilities; import org.apache.hadoop.hive.ql.hooks.ReadEntity; +import org.apache.hadoop.hive.ql.io.AcidUtils; import org.apache.hadoop.hive.ql.io.ContentSummaryInputFormat; import org.apache.hadoop.hive.ql.io.HiveInputFormat; import org.apache.hadoop.hive.ql.metadata.HiveException; @@ -144,8 +145,15 @@ private FetchTask optimize(ParseContext pctx, String alias, TableScanOperator so if (fetch != null && checkThreshold(fetch, limit, pctx)) { FetchWork fetchWork = fetch.convertToWork(); FetchTask fetchTask = (FetchTask) TaskFactory.get(fetchWork); - fetchTask.setCachingEnabled(HiveConf.getBoolVar(pctx.getConf(), - HiveConf.ConfVars.HIVE_FETCH_TASK_CACHING)); + boolean cachingEnabled = HiveConf.getBoolVar(pctx.getConf(), + HiveConf.ConfVars.HIVE_FETCH_TASK_CACHING); + if (cachingEnabled && !AcidUtils.isTransactionalTable(fetch.table)) { + LOG.debug("Fetch task caching is enabled but table {} is not transactional. " + + "Caching is only supported for ACID tables to prevent Cleaner race conditions. Disabling.", + fetch.table.getCompleteName()); + cachingEnabled = false; + } + fetchTask.setCachingEnabled(cachingEnabled); fetchWork.setSink(fetch.completed(pctx, fetchWork)); fetchWork.setSource(source); fetchWork.setLimit(limit);