From c3631df719000455f950230bcd9e7d50737e78b1 Mon Sep 17 00:00:00 2001 From: wenyh1 <2365151147@qq.com> Date: Sun, 8 Oct 2023 17:20:08 +0800 Subject: [PATCH] [inner-2368] fix: when some nodes have been closed during the ddl execution phase, the front side needs to respond with an error. (cherry picked from commit 2cfcac28504a38d7fb05b2ce07df1acb0ba9b810) --- .../mysql/nio/handler/ddl/BaseDDLHandler.java | 14 ++++++++++---- .../handler/ddl/MultiNodeDdlPrepareHandler.java | 11 +++++++---- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/ddl/BaseDDLHandler.java b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/ddl/BaseDDLHandler.java index 2dd1ad712..bd1d2fca0 100644 --- a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/ddl/BaseDDLHandler.java +++ b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/ddl/BaseDDLHandler.java @@ -62,6 +62,7 @@ public abstract class BaseDDLHandler implements ResponseHandler, ExecutableHandl protected final ReentrantLock lock = new ReentrantLock(); protected HashMap nodeResponseStatus = Maps.newHashMap(); + protected Set closedConnSet = new HashSet<>(1); protected AtomicBoolean writeToClientFlag = new AtomicBoolean(false); protected AtomicBoolean specialHandleFlag = new AtomicBoolean(false); // execute special handling only once protected volatile String errMsg; @@ -287,7 +288,7 @@ public abstract class BaseDDLHandler implements ResponseHandler, ExecutableHandl MySQLResponseService responseService = (MySQLResponseService) service; final RouteResultsetNode node = (RouteResultsetNode) responseService.getAttachment(); - if (checkIsAlreadyClosed(node)) return; + if (checkIsAlreadyClosed(node, responseService)) return; LOGGER.warn("backend connect {}, conn info:{}", closeReason0, service); DDLTraceHelper.log(session.getShardingService(), d -> d.infoByNode(node.getName(), stage, DDLTraceHelper.Status.fail, closeReason0)); @@ -326,11 +327,15 @@ public abstract class BaseDDLHandler implements ResponseHandler, ExecutableHandl } } - protected boolean checkIsAlreadyClosed(final RouteResultsetNode node) { + protected boolean checkIsAlreadyClosed(final RouteResultsetNode node, final MySQLResponseService mysqlResponseService) { lock.lock(); try { - if (nodeResponseStatus.get(node) == null || nodeResponseStatus.get(node) == STATUS_CONN_CLOSE) return true; - nodeResponseStatus.put(node, STATUS_CONN_CLOSE); + if (closedConnSet.contains(mysqlResponseService)) { + nodeResponseStatus.put(node, STATUS_CONN_CLOSE); + return true; + } else { + closedConnSet.add(mysqlResponseService); + } session.getTargetMap().remove(node); return false; } finally { @@ -368,6 +373,7 @@ public abstract class BaseDDLHandler implements ResponseHandler, ExecutableHandl protected void clearResources() { nodeResponseStatus.clear(); + closedConnSet.clear(); } protected void handleEndPacket(MySQLPacket packet) { diff --git a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/ddl/MultiNodeDdlPrepareHandler.java b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/ddl/MultiNodeDdlPrepareHandler.java index f42c767e2..7f022dc48 100644 --- a/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/ddl/MultiNodeDdlPrepareHandler.java +++ b/src/main/java/com/actiontech/dble/backend/mysql/nio/handler/ddl/MultiNodeDdlPrepareHandler.java @@ -112,13 +112,16 @@ public class MultiNodeDdlPrepareHandler extends BaseDDLHandler { } @Override - protected boolean checkIsAlreadyClosed(final RouteResultsetNode node) { + protected boolean checkIsAlreadyClosed(final RouteResultsetNode node, final MySQLResponseService mysqlResponseService) { lock.lock(); try { if (finishedTest) return true; - if (nodeResponseStatus.get(node) == null || nodeResponseStatus.get(node) == STATUS_CONN_CLOSE) return true; - nodeResponseStatus.put(node, STATUS_CONN_CLOSE); - session.getTargetMap().remove(node); + if (closedConnSet.contains(mysqlResponseService)) { + nodeResponseStatus.put(node, STATUS_CONN_CLOSE); + return true; + } else { + closedConnSet.add(mysqlResponseService); + } return false; } finally { lock.unlock();