This is an automated email from the ASF dual-hosted git repository.
morrySnow pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new 7a8224fdfbe [feature](query) Support session level
force_forward_all_queries (#66691)
7a8224fdfbe is described below
commit 7a8224fdfbe12f0595b35c5183be1a93003d82fd
Author: yujun <[email protected]>
AuthorDate: Fri Aug 14 14:19:34 2026 +0800
[feature](query) Support session level force_forward_all_queries (#66691)
### What problem does this PR solve?
Problem Summary:
Some users query a freshness/health-check on a follower FE before every
business request. When the follower is replaying a large journal, the
freshness query result can lag and trigger business degradation.
`Config.force_forward_all_queries = true` forces all queries to the
master, but it is cluster-wide and too coarse when clients connect
through a load balancer. The existing session variable
`forward_to_master` does not participate in the ordinary SELECT
forwarding decision.
This PR adds a session-level variable `force_forward_all_queries`. A
query is forwarded to the master when either
`Config.force_forward_all_queries` or the session variable is enabled,
so only the freshness queries need to opt in.
### Release note
Added a session variable `force_forward_all_queries` to force queries of
the session to be forwarded to the master FE.
---
.../java/org/apache/doris/qe/SessionVariable.java | 9 +++
.../java/org/apache/doris/qe/StmtExecutor.java | 3 +-
.../doris/qe/ForceForwardAllQueriesTest.java | 77 ++++++++++++++++++++++
3 files changed, 88 insertions(+), 1 deletion(-)
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
b/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
index 52ac4da4ff8..a1592de2947 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
@@ -214,6 +214,8 @@ public class SessionVariable implements Serializable,
Writable {
// if set to true, some of stmt will be forwarded to master FE to get
result
public static final String FORWARD_TO_MASTER = "forward_to_master";
+ // if set to true, all queries of this session will be forwarded to master
FE
+ public static final String FORCE_FORWARD_ALL_QUERIES =
"force_forward_all_queries";
// user can set instance num after exchange, no need to be equal to nums
of before exchange
public static final String PARALLEL_EXCHANGE_INSTANCE_NUM =
"parallel_exchange_instance_num";
public static final String SHOW_HIDDEN_COLUMNS = "show_hidden_columns";
@@ -1568,6 +1570,9 @@ public class SessionVariable implements Serializable,
Writable {
@VarAttrDef.VarAttr(name = FORWARD_TO_MASTER)
public boolean forwardToMaster = true;
+ @VarAttrDef.VarAttr(name = FORCE_FORWARD_ALL_QUERIES)
+ public boolean forceForwardAllQueries = false;
+
// compatible with some mysql client connect, say DataGrip of JetBrains
@VarAttrDef.VarAttr(name = EVENT_SCHEDULER)
public String eventScheduler = "OFF";
@@ -4464,6 +4469,10 @@ public class SessionVariable implements Serializable,
Writable {
return forwardToMaster;
}
+ public boolean isForceForwardAllQueries() {
+ return forceForwardAllQueries;
+ }
+
// for unit test
public String getEventScheduler() {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java
b/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java
index 17235a7bf15..902bbfb4646 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java
@@ -463,7 +463,8 @@ public class StmtExecutor {
// this is a query stmt, but this non-master FE can not read, forward
it to master
if (isQuery() && !Env.getCurrentEnv().isMaster()
- && (!Env.getCurrentEnv().canRead() || debugForwardAllQueries()
|| Config.force_forward_all_queries)) {
+ && (!Env.getCurrentEnv().canRead() || debugForwardAllQueries()
|| Config.force_forward_all_queries
+ ||
context.getSessionVariable().isForceForwardAllQueries())) {
return true;
}
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/qe/ForceForwardAllQueriesTest.java
b/fe/fe-core/src/test/java/org/apache/doris/qe/ForceForwardAllQueriesTest.java
new file mode 100644
index 00000000000..d0ca148e69d
--- /dev/null
+++
b/fe/fe-core/src/test/java/org/apache/doris/qe/ForceForwardAllQueriesTest.java
@@ -0,0 +1,77 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.qe;
+
+import org.apache.doris.analysis.StatementBase;
+import org.apache.doris.catalog.Env;
+import org.apache.doris.common.Config;
+import org.apache.doris.common.jmockit.Deencapsulation;
+import org.apache.doris.ha.FrontendNodeType;
+import org.apache.doris.utframe.TestWithFeService;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+public class ForceForwardAllQueriesTest extends TestWithFeService {
+
+ @Test
+ public void testSessionForceForwardAllQueries() throws Exception {
+ Config.force_forward_all_queries = false;
+ Config.enable_bdbje_debug_mode = false;
+
+ Env env = Env.getCurrentEnv();
+ FrontendNodeType originalFeType = env.getFeType();
+ AtomicBoolean canRead = Deencapsulation.getField(env, "canRead");
+ Deencapsulation.setField(env, "feType", FrontendNodeType.FOLLOWER);
+ canRead.set(true);
+ try {
+ ConnectContext ctx = createDefaultCtx();
+ ctx.setThreadLocalInfo();
+ StatementBase parsedStmt = analyzeAndGetStmtByNereids("select 1",
ctx);
+ StmtExecutor executor = new StmtExecutor(ctx, parsedStmt);
+
+ // neither session variable nor config enabled -> not forwarded
+ ctx.getSessionVariable().forceForwardAllQueries = false;
+ Config.force_forward_all_queries = false;
+ boolean forward = Deencapsulation.invoke(executor,
"shouldForwardToMaster");
+ Assert.assertFalse(forward);
+
+ // session variable enabled -> forwarded
+ ctx.getSessionVariable().forceForwardAllQueries = true;
+ forward = Deencapsulation.invoke(executor,
"shouldForwardToMaster");
+ Assert.assertTrue(forward);
+
+ // session variable disabled but config enabled -> forwarded
+ ctx.getSessionVariable().forceForwardAllQueries = false;
+ Config.force_forward_all_queries = true;
+ forward = Deencapsulation.invoke(executor,
"shouldForwardToMaster");
+ Assert.assertTrue(forward);
+
+ // both disabled -> not forwarded
+ Config.force_forward_all_queries = false;
+ forward = Deencapsulation.invoke(executor,
"shouldForwardToMaster");
+ Assert.assertFalse(forward);
+ } finally {
+ Deencapsulation.setField(env, "feType", originalFeType);
+ canRead.set(false);
+ Config.force_forward_all_queries = false;
+ }
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]