This is an automated email from the ASF dual-hosted git repository.

CRZbulabula pushed a commit to branch yongzao/revert-region-replica-procedure
in repository https://gitbox.apache.org/repos/asf/iotdb.git

commit 36f15f85531116f8f8966cb681f57c789ba6a335
Author: Yongzao <[email protected]>
AuthorDate: Wed Aug 5 13:49:21 2026 +0800

    Revert "Use procedures for region create/delete to fix the delete-region 
ghost task (#18033)"
    
    This reverts commit 3b7df259b8dc49827c07c4d755473c99315b2b96.
---
 .../iotdb/confignode/i18n/ConfigNodeMessages.java  |   4 -
 .../iotdb/confignode/i18n/ManagerMessages.java     |   5 +-
 .../iotdb/confignode/i18n/ProcedureMessages.java   |  14 -
 .../iotdb/confignode/i18n/ConfigNodeMessages.java  |   6 -
 .../iotdb/confignode/i18n/ManagerMessages.java     |   5 +-
 .../iotdb/confignode/i18n/ProcedureMessages.java   |  16 -
 .../client/async/CnToDnAsyncRequestType.java       |   1 +
 .../CnToDnInternalServiceAsyncRequestManager.java  |   5 +
 .../iotdb/confignode/manager/ProcedureManager.java |   4 +
 .../manager/partition/PartitionManager.java        | 330 +++++++++++++--------
 .../persistence/partition/PartitionInfo.java       |  29 +-
 .../impl/region/CreateRegionGroupsProcedure.java   |  22 +-
 .../impl/region/RemoveRegionGroupProcedure.java    | 284 ------------------
 .../impl/schema/DeleteDatabaseProcedure.java       |  94 +++++-
 .../procedure/state/RemoveRegionGroupState.java    |  24 --
 .../state/schema/DeleteDatabaseState.java          |   5 +-
 .../procedure/store/ProcedureFactory.java          |   6 -
 .../confignode/procedure/store/ProcedureType.java  |   1 -
 .../confignode/persistence/PartitionInfoTest.java  |  27 --
 .../region/RemoveRegionGroupProcedureTest.java     |  72 -----
 .../iotdb/db/service/RegionMigrateService.java     |  12 +-
 21 files changed, 315 insertions(+), 651 deletions(-)

diff --git 
a/iotdb-core/confignode/src/main/i18n/en/org/apache/iotdb/confignode/i18n/ConfigNodeMessages.java
 
b/iotdb-core/confignode/src/main/i18n/en/org/apache/iotdb/confignode/i18n/ConfigNodeMessages.java
index 54e06e9a972..5e79dffbffc 100644
--- 
a/iotdb-core/confignode/src/main/i18n/en/org/apache/iotdb/confignode/i18n/ConfigNodeMessages.java
+++ 
b/iotdb-core/confignode/src/main/i18n/en/org/apache/iotdb/confignode/i18n/ConfigNodeMessages.java
@@ -642,10 +642,6 @@ public final class ConfigNodeMessages {
       "Unexpected interruption while waiting for ConfigNode leader load 
warm-up.";
   public static final String 
EXCEPTION_PROCEDURE_FILE_ARG_EXCEEDS_THE_LOAD_BUFFER_LIMIT_ARG_ACTUAL_SIZE_ARG_62375B4C
 =
       "Procedure file %s exceeds the load buffer limit %s, actual size %s";
-  public static final String 
MESSAGE_DROPPING_LEGACY_REGION_DELETE_TASK_FOR_ARG_WHILE_REPLAYING_OFFER_PLAN_REGION_DELETION_IS_NOW_HANDLED_BY_REMOVEREGIONGROUPPROCEDURE_2A81A649
 =
-      "Dropping legacy region-delete task for {} while replaying offer plan; 
region deletion is now handled by RemoveRegionGroupProcedure.";
-  public static final String 
MESSAGE_DROPPING_LEGACY_REGION_DELETE_TASK_FOR_ARG_WHILE_LOADING_SNAPSHOT_REGION_DELETION_IS_NOW_HANDLED_BY_REMOVEREGIONGROUPPROCEDURE_A9D409A0
 =
-      "Dropping legacy region-delete task for {} while loading snapshot; 
region deletion is now handled by RemoveRegionGroupProcedure.";
   public static final String 
MESSAGE_CONFIGNODE_LEADER_IS_WARMING_UP_BEFORE_SERVING_THE_REGISTERING_CONFIGNODE_WILL_WAIT_2E051639
 =
       "ConfigNode leader is warming up before serving the registering 
ConfigNode, will wait";
   public static final String 
MESSAGE_CONFIGNODE_LEADER_IS_WARMING_UP_BEFORE_SERVING_THE_REGISTERING_CONFIGNODE_WILL_WAIT_AND_RETRY_STATUS_ARG_RETRY_ARG_3C924873
 =
diff --git 
a/iotdb-core/confignode/src/main/i18n/en/org/apache/iotdb/confignode/i18n/ManagerMessages.java
 
b/iotdb-core/confignode/src/main/i18n/en/org/apache/iotdb/confignode/i18n/ManagerMessages.java
index 13bfaf6de8a..10ea4763af9 100644
--- 
a/iotdb-core/confignode/src/main/i18n/en/org/apache/iotdb/confignode/i18n/ManagerMessages.java
+++ 
b/iotdb-core/confignode/src/main/i18n/en/org/apache/iotdb/confignode/i18n/ManagerMessages.java
@@ -73,6 +73,7 @@ public final class ManagerMessages {
       "DataRegionGroupExtensionPolicy %s doesn't exist.";
   public static final String DECREASE_REFERENCE_COUNT_FOR_SNAPSHOT_ERROR =
       "Decrease reference count for snapshot {} error.";
+  public static final String DELETING_REGIONS_COSTS_MS = "Deleting regions 
costs {}ms";
   public static final String 
DETECTED_HISTORICAL_PIPE_COMPLETION_REPORT_FROM_DATANODE =
       "Detected historical pipe completion report from DataNode {} for pipe 
{}. remainingEventCount: {}, remainingTime: {}, completedDataNodes: {}";
   public static final String DETECTED_COMPLETION_OF_PIPE_STATIC_META_REMOVE_IT 
=
@@ -440,6 +441,8 @@ public final class ManagerMessages {
       "Start to create Region: {} on DataNode: {}";
   public static final String START_TO_CREATE_UDF_ON_DATA_NODES_NEEDTOSAVEJAR =
       "Start to create UDF [{}] on Data Nodes, needToSaveJar[{}]";
+  public static final String START_TO_DELETE_REGION_ON_DATANODE =
+      "Start to delete Region: {} on DataNode: {}";
   public static final String START_TRANSFER_OF = "Start transfer of {}";
   public static final String STOP_SUBMITTING_CQ_BECAUSE = "Stop submitting CQ 
{} because {}";
   public static final String 
STOP_SUBMITTING_CQ_BECAUSE_CURRENT_NODE_IS_NOT_LEADER_OR =
@@ -522,8 +525,6 @@ public final class ManagerMessages {
       "Unexpected interruption during waiting for configNode leader ready.";
   public static final String 
UNEXPECTED_INTERRUPTION_DURING_WAITING_FOR_GET_CLUSTER_ID =
       "Unexpected interruption during waiting for get cluster id.";
-  public static final String 
UNEXPECTED_NON_CREATE_REGION_MAINTAIN_TASK_SKIPPED =
-      "Unexpected non-create task in the RegionMaintainer queue; skipping it 
(the queue only recreates region replicas now, and region deletion is handled 
by RemoveRegionGroupProcedure).";
   public static final String 
UNEXPECTED_NULL_PROCEDURE_PARAMETERS_FOR_WAITINGPROCEDUREFINISHED =
       "Unexpected null procedure parameters for waitingProcedureFinished";
   public static final String 
UNKNOWN_DATAPARTITION_ALLOCATION_STRATEGY_USING_INHERIT_STRATEGY_BY_DEFAULT =
diff --git 
a/iotdb-core/confignode/src/main/i18n/en/org/apache/iotdb/confignode/i18n/ProcedureMessages.java
 
b/iotdb-core/confignode/src/main/i18n/en/org/apache/iotdb/confignode/i18n/ProcedureMessages.java
index 775c64ed2c4..b29244d4117 100644
--- 
a/iotdb-core/confignode/src/main/i18n/en/org/apache/iotdb/confignode/i18n/ProcedureMessages.java
+++ 
b/iotdb-core/confignode/src/main/i18n/en/org/apache/iotdb/confignode/i18n/ProcedureMessages.java
@@ -632,16 +632,6 @@ public final class ProcedureMessages {
   public static final String PID_ADDREGION_STATE_FAILED = "[pid{}][AddRegion] 
state {} failed";
   public static final String 
PID_ADDREGION_SUCCESS_HAS_BEEN_ADDED_TO_DATANODE_PROCEDURE_TOOK =
       "[pid{}][AddRegion] success, {} has been added to DataNode {}. Procedure 
took {} (start at {}).";
-  public static final String PID_REMOVEREGIONGROUP_STARTED_WILL_BE_DELETED =
-      "[pid{}][RemoveRegionGroup] started, region group {} will be deleted 
from DataNodes {}.";
-  public static final String 
PID_REMOVEREGIONGROUP_STARTED_REPLICA_WILL_BE_DELETED_FROM_DATANODE =
-      "[pid{}][RemoveRegionGroup] region {} will be deleted from DataNode {}.";
-  public static final String PID_REMOVEREGIONGROUP_STATE_FAILED =
-      "[pid{}][RemoveRegionGroup] state {} failed";
-  public static final String PID_REMOVEREGIONGROUP_DELETE_REPLICA_FAILED =
-      "[pid{}][RemoveRegionGroup] failed to delete a replica of region {} 
(attempt {}/{}), will retry. reason: {}";
-  public static final String PID_REMOVEREGIONGROUP_SUCCESS_PROCEDURE_TOOK =
-      "[pid{}][RemoveRegionGroup] success, region group {} has been deleted. 
Procedure took {} (started at {}).";
   public static final String 
PID_MIGRATEREGION_STARTED_WILL_BE_MIGRATED_FROM_DATANODE_TO =
       "[pid{}][MigrateRegion] started, {} will be migrated from DataNode {} to 
{}.";
   public static final String PID_MIGRATEREGION_STATE_COMPLETE =
@@ -1398,10 +1388,6 @@ public final class ProcedureMessages {
   public static final String LOG_ARG_8393DD4A = "{}";
   public static final String MESSAGE_HALT_PID_ARG_ACTIVECOUNT_ARG_411F3EBF = 
"Halt pid={}, activeCount={}";
   public static final String 
MESSAGE_EXCEPTION_HAPPENED_WHEN_WORKER_ARG_EXECUTE_PROCEDURE_ARG_6E3AD27D = 
"Exception happened when worker {} execute procedure {}";
-  public static final String 
EXCEPTION_CANNOT_DERIVE_A_COLLISION_FREE_DELETE_TASKID_PROCID_ARG_DELETETASKSEQ_ARG_EXCEED_THE_71B7046A
 =
-      "cannot derive a collision-free delete taskId: procId=%d, 
deleteTaskSeq=%d exceed the ";
-  public static final String 
EXCEPTION_CANNOT_DERIVE_A_COLLISION_FREE_DELETE_TASKID_PROCID_ARG_DELETETASKSEQ_ARG_EXCEED_THE_ARG_ARG_BIT_BUDGET_015C598D
 =
-      "cannot derive a collision-free delete taskId: procId=%d, 
deleteTaskSeq=%d exceed the %d/%d-bit budget";
   public static final String 
MESSAGE_FAILED_TO_SHOW_DATAPARTITIONTABLE_INTEGRITY_CHECK_PROGRESS_5EE98694 = 
"Failed to show DataPartitionTable integrity check progress";
   public static final String 
MESSAGE_ENCOUNTERED_UNEXPECTED_DATAPARTITIONTABLEINTEGRITYCHECKPROCEDURESTATE_ARG_WHEN_SHOWING_PROGRESS_5FA2739F
 =
       "Encountered unexpected DataPartitionTableIntegrityCheckProcedureState 
{} when showing progress";
diff --git 
a/iotdb-core/confignode/src/main/i18n/zh/org/apache/iotdb/confignode/i18n/ConfigNodeMessages.java
 
b/iotdb-core/confignode/src/main/i18n/zh/org/apache/iotdb/confignode/i18n/ConfigNodeMessages.java
index 0c28efc4096..5f9a0d8d9ab 100644
--- 
a/iotdb-core/confignode/src/main/i18n/zh/org/apache/iotdb/confignode/i18n/ConfigNodeMessages.java
+++ 
b/iotdb-core/confignode/src/main/i18n/zh/org/apache/iotdb/confignode/i18n/ConfigNodeMessages.java
@@ -679,12 +679,6 @@ public final class ConfigNodeMessages {
   public static final String
       
EXCEPTION_PROCEDURE_FILE_ARG_EXCEEDS_THE_LOAD_BUFFER_LIMIT_ARG_ACTUAL_SIZE_ARG_62375B4C
 =
           "Procedure 文件 %s 超过了加载缓冲区限制 %s,实际大小为 %s";
-  public static final String
-      
MESSAGE_DROPPING_LEGACY_REGION_DELETE_TASK_FOR_ARG_WHILE_REPLAYING_OFFER_PLAN_REGION_DELETION_IS_NOW_HANDLED_BY_REMOVEREGIONGROUPPROCEDURE_2A81A649
 =
-          "重放 offer plan 时丢弃 {} 的遗留 region-delete 任务;region 删除现已由 
RemoveRegionGroupProcedure 处理。";
-  public static final String
-      
MESSAGE_DROPPING_LEGACY_REGION_DELETE_TASK_FOR_ARG_WHILE_LOADING_SNAPSHOT_REGION_DELETION_IS_NOW_HANDLED_BY_REMOVEREGIONGROUPPROCEDURE_A9D409A0
 =
-          "加载快照时丢弃 {} 的遗留 region-delete 任务;region 删除现已由 
RemoveRegionGroupProcedure 处理。";
   public static final String
       
MESSAGE_CONFIGNODE_LEADER_IS_WARMING_UP_BEFORE_SERVING_THE_REGISTERING_CONFIGNODE_WILL_WAIT_2E051639
 =
           "ConfigNode leader 在服务注册中的 ConfigNode 前正在进行预热,将等待";
diff --git 
a/iotdb-core/confignode/src/main/i18n/zh/org/apache/iotdb/confignode/i18n/ManagerMessages.java
 
b/iotdb-core/confignode/src/main/i18n/zh/org/apache/iotdb/confignode/i18n/ManagerMessages.java
index 42aa21f46ae..499e922f7a7 100644
--- 
a/iotdb-core/confignode/src/main/i18n/zh/org/apache/iotdb/confignode/i18n/ManagerMessages.java
+++ 
b/iotdb-core/confignode/src/main/i18n/zh/org/apache/iotdb/confignode/i18n/ManagerMessages.java
@@ -73,6 +73,7 @@ public final class ManagerMessages {
       "DataRegionGroupExtensionPolicy %s 不存在。";
   public static final String DECREASE_REFERENCE_COUNT_FOR_SNAPSHOT_ERROR =
       "减少快照 {} 的引用计数失败。";
+  public static final String DELETING_REGIONS_COSTS_MS = "删除 region 耗时 {}ms";
   public static final String 
DETECTED_HISTORICAL_PIPE_COMPLETION_REPORT_FROM_DATANODE =
       "检测到来自 DataNode {} 的历史 pipe 完成上报,pipe {}。remainingEventCount: {}, 
remainingTime: {}, completedDataNodes: {}";
   public static final String DETECTED_COMPLETION_OF_PIPE_STATIC_META_REMOVE_IT 
=
@@ -435,6 +436,8 @@ public final class ManagerMessages {
       "开始在 DataNode: {} 上创建 Region:{}";
   public static final String START_TO_CREATE_UDF_ON_DATA_NODES_NEEDTOSAVEJAR =
       "开始在 Data Nodes 上创建 UDF [{}],needToSaveJar[{}]";
+  public static final String START_TO_DELETE_REGION_ON_DATANODE =
+      "开始在 DataNode: {} 上删除 Region:{}";
   public static final String START_TRANSFER_OF = "开始传输 {}";
   public static final String STOP_SUBMITTING_CQ_BECAUSE = "停止提交 CQ {},原因:{}";
   public static final String 
STOP_SUBMITTING_CQ_BECAUSE_CURRENT_NODE_IS_NOT_LEADER_OR =
@@ -517,8 +520,6 @@ public final class ManagerMessages {
       "等待 configNode leader 就绪过程中发生意外中断。";
   public static final String 
UNEXPECTED_INTERRUPTION_DURING_WAITING_FOR_GET_CLUSTER_ID =
       "等待获取 cluster id 过程中发生意外中断。";
-  public static final String 
UNEXPECTED_NON_CREATE_REGION_MAINTAIN_TASK_SKIPPED =
-      "RegionMaintainer 队列中出现意外的非 create 任务;跳过处理(该队列目前仅用于重建 region 副本,region 
删除由 RemoveRegionGroupProcedure 处理)。";
   public static final String 
UNEXPECTED_NULL_PROCEDURE_PARAMETERS_FOR_WAITINGPROCEDUREFINISHED =
       "waitingProcedureFinished 的 procedure 参数为空";
   public static final String 
UNKNOWN_DATAPARTITION_ALLOCATION_STRATEGY_USING_INHERIT_STRATEGY_BY_DEFAULT =
diff --git 
a/iotdb-core/confignode/src/main/i18n/zh/org/apache/iotdb/confignode/i18n/ProcedureMessages.java
 
b/iotdb-core/confignode/src/main/i18n/zh/org/apache/iotdb/confignode/i18n/ProcedureMessages.java
index 8f628e58ba5..0569e1b6261 100644
--- 
a/iotdb-core/confignode/src/main/i18n/zh/org/apache/iotdb/confignode/i18n/ProcedureMessages.java
+++ 
b/iotdb-core/confignode/src/main/i18n/zh/org/apache/iotdb/confignode/i18n/ProcedureMessages.java
@@ -598,16 +598,6 @@ public final class ProcedureMessages {
   public static final String PID_ADDREGION_STATE_FAILED = "[pid{}][AddRegion] 
状态 {} 失败";
   public static final String 
PID_ADDREGION_SUCCESS_HAS_BEEN_ADDED_TO_DATANODE_PROCEDURE_TOOK =
       "[pid{}][AddRegion] 成功,{} 已添加到 DataNode {}。Procedure 耗时 {}(开始于 {})。";
-  public static final String PID_REMOVEREGIONGROUP_STARTED_WILL_BE_DELETED =
-      "[pid{}][RemoveRegionGroup] 开始,region group {} 将从 DataNode {} 上删除。";
-  public static final String 
PID_REMOVEREGIONGROUP_STARTED_REPLICA_WILL_BE_DELETED_FROM_DATANODE =
-      "[pid{}][RemoveRegionGroup] region {} 将从 DataNode {} 上删除。";
-  public static final String PID_REMOVEREGIONGROUP_STATE_FAILED =
-      "[pid{}][RemoveRegionGroup] 状态 {} 失败";
-  public static final String PID_REMOVEREGIONGROUP_DELETE_REPLICA_FAILED =
-      "[pid{}][RemoveRegionGroup] 删除 region {} 的一个副本失败(第 {}/{} 次尝试),将重试。原因:{}";
-  public static final String PID_REMOVEREGIONGROUP_SUCCESS_PROCEDURE_TOOK =
-      "[pid{}][RemoveRegionGroup] 成功,region group {} 已删除。过程耗时 {}(开始于 {})。";
   public static final String 
PID_MIGRATEREGION_STARTED_WILL_BE_MIGRATED_FROM_DATANODE_TO =
       "[pid{}][MigrateRegion] 开始,{} 将从 DataNode {} 迁移到 {}。";
   public static final String PID_MIGRATEREGION_STATE_COMPLETE = 
"[pid{}][MigrateRegion] 状态 {} 完成";
@@ -1469,12 +1459,6 @@ public final class ProcedureMessages {
   public static final String
       
MESSAGE_EXCEPTION_HAPPENED_WHEN_WORKER_ARG_EXECUTE_PROCEDURE_ARG_6E3AD27D =
           "worker {} 执行 procedure {} 时发生异常";
-  public static final String
-      
EXCEPTION_CANNOT_DERIVE_A_COLLISION_FREE_DELETE_TASKID_PROCID_ARG_DELETETASKSEQ_ARG_EXCEED_THE_71B7046A
 =
-          "无法推导出无冲突的 delete taskId:procId=%d,deleteTaskSeq=%d 超出了 ";
-  public static final String
-      
EXCEPTION_CANNOT_DERIVE_A_COLLISION_FREE_DELETE_TASKID_PROCID_ARG_DELETETASKSEQ_ARG_EXCEED_THE_ARG_ARG_BIT_BUDGET_015C598D
 =
-          "无法推导出无冲突的 delete taskId:procId=%d,deleteTaskSeq=%d 超出了 %d/%d 位的预算";
   public static final String
       
MESSAGE_FAILED_TO_SHOW_DATAPARTITIONTABLE_INTEGRITY_CHECK_PROGRESS_5EE98694 =
           "显示 DataPartitionTable 完整性检查进度失败";
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/client/async/CnToDnAsyncRequestType.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/client/async/CnToDnAsyncRequestType.java
index cc28fed0ff5..2946884e373 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/client/async/CnToDnAsyncRequestType.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/client/async/CnToDnAsyncRequestType.java
@@ -39,6 +39,7 @@ public enum CnToDnAsyncRequestType {
   // Region Maintenance
   CREATE_DATA_REGION,
   CREATE_SCHEMA_REGION,
+  DELETE_REGION,
   RESET_PEER_LIST,
   NOTIFY_REGION_MIGRATION,
   UPDATE_REGION_ROUTE_MAP,
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/client/async/CnToDnInternalServiceAsyncRequestManager.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/client/async/CnToDnInternalServiceAsyncRequestManager.java
index 9c90c469137..4f66330f6ec 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/client/async/CnToDnInternalServiceAsyncRequestManager.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/client/async/CnToDnInternalServiceAsyncRequestManager.java
@@ -19,6 +19,7 @@
 
 package org.apache.iotdb.confignode.client.async;
 
+import org.apache.iotdb.common.rpc.thrift.TConsensusGroupId;
 import org.apache.iotdb.common.rpc.thrift.TDataNodeLocation;
 import org.apache.iotdb.common.rpc.thrift.TFlushReq;
 import org.apache.iotdb.common.rpc.thrift.TNodeLocations;
@@ -142,6 +143,10 @@ public class CnToDnInternalServiceAsyncRequestManager
         (req, client, handler) ->
             client.createDataRegion(
                 (TCreateDataRegionReq) req, (DataNodeTSStatusRPCHandler) 
handler));
+    actionMapBuilder.put(
+        CnToDnAsyncRequestType.DELETE_REGION,
+        (req, client, handler) ->
+            client.deleteRegion((TConsensusGroupId) req, 
(DataNodeTSStatusRPCHandler) handler));
     actionMapBuilder.put(
         CnToDnAsyncRequestType.CREATE_SCHEMA_REGION,
         (req, client, handler) ->
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ProcedureManager.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ProcedureManager.java
index bd987cd42a6..45cea0a31e3 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ProcedureManager.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ProcedureManager.java
@@ -59,6 +59,7 @@ import 
org.apache.iotdb.confignode.consensus.request.write.datanode.RemoveDataNo
 import 
org.apache.iotdb.confignode.consensus.request.write.procedure.UpdateProcedurePlan;
 import 
org.apache.iotdb.confignode.consensus.request.write.region.CreateRegionGroupsPlan;
 import org.apache.iotdb.confignode.i18n.ManagerMessages;
+import org.apache.iotdb.confignode.manager.partition.PartitionManager;
 import 
org.apache.iotdb.confignode.manager.subscription.SubscriptionCoordinator;
 import org.apache.iotdb.confignode.persistence.ProcedureInfo;
 import org.apache.iotdb.confignode.procedure.PartitionTableAutoCleaner;
@@ -339,6 +340,9 @@ public class ProcedureManager {
     }
     List<TSStatus> results = new ArrayList<>(procedures.size());
     procedures.forEach(procedure -> 
results.add(waitingProcedureFinished(procedure)));
+    // Clear the previously deleted regions
+    final PartitionManager partitionManager = 
getConfigManager().getPartitionManager();
+    
partitionManager.getRegionMaintainer().submit(partitionManager::maintainRegionReplicas);
     if (results.stream()
         .allMatch(result -> result.getCode() == 
TSStatusCode.SUCCESS_STATUS.getStatusCode())) {
       return StatusUtils.OK;
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/partition/PartitionManager.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/partition/PartitionManager.java
index 7efdae278db..4b5606865b5 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/partition/PartitionManager.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/partition/PartitionManager.java
@@ -84,7 +84,9 @@ import org.apache.iotdb.confignode.manager.node.NodeManager;
 import org.apache.iotdb.confignode.manager.schema.ClusterSchemaManager;
 import org.apache.iotdb.confignode.persistence.partition.PartitionInfo;
 import 
org.apache.iotdb.confignode.persistence.partition.maintainer.RegionCreateTask;
+import 
org.apache.iotdb.confignode.persistence.partition.maintainer.RegionDeleteTask;
 import 
org.apache.iotdb.confignode.persistence.partition.maintainer.RegionMaintainTask;
+import 
org.apache.iotdb.confignode.persistence.partition.maintainer.RegionMaintainType;
 import 
org.apache.iotdb.confignode.procedure.impl.partition.DataPartitionTableIntegrityCheckProcedure;
 import org.apache.iotdb.confignode.rpc.thrift.TCountTimeSlotListReq;
 import org.apache.iotdb.confignode.rpc.thrift.TGetRegionGroupsByTimeReq;
@@ -108,7 +110,6 @@ import org.slf4j.LoggerFactory;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.EnumMap;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
@@ -1356,139 +1357,218 @@ public class PartitionManager {
   /**
    * Called by {@link PartitionManager#regionMaintainer}.
    *
-   * <p>Periodically recreate the failed RegionReplicas offered to the 
RegionMaintainer queue.
-   * Region deletion is owned by {@code RemoveRegionGroupProcedure} and is no 
longer handled here.
+   * <p>Periodically maintain the RegionReplicas to be created or deleted
    */
   public void maintainRegionReplicas() {
     // The consensusManager of configManager may not be fully initialized at 
this time
-    if (getConsensusManager() == null || !getConsensusManager().isLeader()) {
-      return;
-    }
-
-    // Group the queued tasks into one FIFO sub-queue per region. The queue 
only ever holds
-    // RegionCreateTasks now (delete tasks are filtered out at the 
PartitionInfo ingestion points),
-    // and a region may carry several of them when more than one of its 
replicas failed to create.
-    final Map<TConsensusGroupId, Queue<RegionCreateTask>> tasksByRegion = new 
HashMap<>();
-    for (RegionMaintainTask task : partitionInfo.getRegionMaintainEntryList()) 
{
-      if (!(task instanceof RegionCreateTask)) {
-        // Unreachable: the queue only holds create tasks now (legacy delete 
tasks are dropped at
-        // the
-        // PartitionInfo ingestion points). Guard against a regression so an 
unexpected task type
-        // cannot silently stall the loop.
-        
LOGGER.warn(ManagerMessages.UNEXPECTED_NON_CREATE_REGION_MAINTAIN_TASK_SKIPPED);
-        continue;
-      }
-      tasksByRegion
-          .computeIfAbsent(task.getRegionId(), k -> new LinkedList<>())
-          .add((RegionCreateTask) task);
-    }
-
-    // Drain the sub-queues head-by-head. Each round takes the head of every 
region, batches those
-    // heads by region type into a single create RPC per type, then durably 
polls the tasks that
-    // succeeded. Tasks of the same region are advanced one at a time to 
preserve their offer order.
-    while (!tasksByRegion.isEmpty()) {
-      final Map<TConsensusGroupType, List<RegionCreateTask>> headsByType =
-          new EnumMap<>(TConsensusGroupType.class);
-      for (Queue<RegionCreateTask> queue : tasksByRegion.values()) {
-        final RegionCreateTask head = queue.peek();
-        headsByType.computeIfAbsent(head.getRegionId().getType(), k -> new 
ArrayList<>()).add(head);
-      }
-
-      final Set<TConsensusGroupId> successfulRegions = new HashSet<>();
-      int selectedCount = 0;
-      for (Map.Entry<TConsensusGroupType, List<RegionCreateTask>> entry : 
headsByType.entrySet()) {
-        selectedCount += entry.getValue().size();
-        successfulRegions.addAll(submitRegionCreateTasks(entry.getKey(), 
entry.getValue()));
-      }
+    Optional.ofNullable(getConsensusManager())
+        .ifPresent(
+            consensusManager -> {
+              if (getConsensusManager().isLeader()) {
+                List<RegionMaintainTask> regionMaintainTaskList =
+                    partitionInfo.getRegionMaintainEntryList();
+
+                if (regionMaintainTaskList.isEmpty()) {
+                  return;
+                }
+
+                // Group tasks by region id
+                Map<TConsensusGroupId, Queue<RegionMaintainTask>> 
regionMaintainTaskMap =
+                    new HashMap<>();
+                for (RegionMaintainTask regionMaintainTask : 
regionMaintainTaskList) {
+                  regionMaintainTaskMap
+                      .computeIfAbsent(regionMaintainTask.getRegionId(), k -> 
new LinkedList<>())
+                      .add(regionMaintainTask);
+                }
+
+                while (!regionMaintainTaskMap.isEmpty()) {
+                  // Select same type task from each region group
+                  List<RegionMaintainTask> selectedRegionMaintainTask = new 
ArrayList<>();
+                  RegionMaintainType currentType = null;
+                  for (Map.Entry<TConsensusGroupId, Queue<RegionMaintainTask>> 
entry :
+                      regionMaintainTaskMap.entrySet()) {
+                    RegionMaintainTask regionMaintainTask = 
entry.getValue().peek();
+                    if (regionMaintainTask == null) {
+                      continue;
+                    }
+
+                    if (currentType == null) {
+                      currentType = regionMaintainTask.getType();
+                      selectedRegionMaintainTask.add(entry.getValue().peek());
+                    } else {
+                      if (!currentType.equals(regionMaintainTask.getType())) {
+                        continue;
+                      }
+
+                      if (currentType.equals(RegionMaintainType.DELETE)
+                          || entry
+                              .getKey()
+                              .getType()
+                              
.equals(selectedRegionMaintainTask.get(0).getRegionId().getType())) {
+                        // Delete or same create task
+                        
selectedRegionMaintainTask.add(entry.getValue().peek());
+                      }
+                    }
+                  }
 
-      if (successfulRegions.isEmpty()) {
-        break;
-      }
+                  if (selectedRegionMaintainTask.isEmpty()) {
+                    break;
+                  }
 
-      // Advance the in-memory sub-queues so the next round picks the 
following task of each region.
-      for (TConsensusGroupId regionId : successfulRegions) {
-        tasksByRegion.computeIfPresent(
-            regionId,
-            (k, queue) -> {
-              queue.poll();
-              return queue.isEmpty() ? null : queue;
-            });
-      }
+                  Set<TConsensusGroupId> successfulTask = new HashSet<>();
+                  switch (currentType) {
+                    case CREATE:
+                      // create region
+                      switch 
(selectedRegionMaintainTask.get(0).getRegionId().getType()) {
+                        case SchemaRegion:
+                          // create SchemaRegion
+                          DataNodeAsyncRequestContext<TCreateSchemaRegionReq, 
TSStatus>
+                              createSchemaRegionHandler =
+                                  new DataNodeAsyncRequestContext<>(
+                                      
CnToDnAsyncRequestType.CREATE_SCHEMA_REGION);
+                          for (RegionMaintainTask regionMaintainTask : 
selectedRegionMaintainTask) {
+                            RegionCreateTask schemaRegionCreateTask =
+                                (RegionCreateTask) regionMaintainTask;
+                            LOGGER.info(
+                                
ManagerMessages.START_TO_CREATE_REGION_ON_DATANODE,
+                                
schemaRegionCreateTask.getRegionReplicaSet().getRegionId(),
+                                schemaRegionCreateTask.getTargetDataNode());
+                            createSchemaRegionHandler.putRequest(
+                                schemaRegionCreateTask.getRegionId().getId(),
+                                new TCreateSchemaRegionReq(
+                                    
schemaRegionCreateTask.getRegionReplicaSet(),
+                                    schemaRegionCreateTask.getStorageGroup()));
+                            createSchemaRegionHandler.putNodeLocation(
+                                schemaRegionCreateTask.getRegionId().getId(),
+                                schemaRegionCreateTask.getTargetDataNode());
+                          }
+
+                          
CnToDnInternalServiceAsyncRequestManager.getInstance()
+                              
.sendAsyncRequestWithRetry(createSchemaRegionHandler);
+
+                          for (Map.Entry<Integer, TSStatus> entry :
+                              
createSchemaRegionHandler.getResponseMap().entrySet()) {
+                            if (entry.getValue().getCode()
+                                == 
TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+                              successfulTask.add(
+                                  new TConsensusGroupId(
+                                      TConsensusGroupType.SchemaRegion, 
entry.getKey()));
+                            }
+                          }
+                          break;
+                        case DataRegion:
+                          // Create DataRegion
+                          DataNodeAsyncRequestContext<TCreateDataRegionReq, 
TSStatus>
+                              createDataRegionHandler =
+                                  new DataNodeAsyncRequestContext<>(
+                                      
CnToDnAsyncRequestType.CREATE_DATA_REGION);
+                          for (RegionMaintainTask regionMaintainTask : 
selectedRegionMaintainTask) {
+                            RegionCreateTask dataRegionCreateTask =
+                                (RegionCreateTask) regionMaintainTask;
+                            LOGGER.info(
+                                
ManagerMessages.START_TO_CREATE_REGION_ON_DATANODE,
+                                
dataRegionCreateTask.getRegionReplicaSet().getRegionId(),
+                                dataRegionCreateTask.getTargetDataNode());
+                            createDataRegionHandler.putRequest(
+                                dataRegionCreateTask.getRegionId().getId(),
+                                new TCreateDataRegionReq(
+                                    dataRegionCreateTask.getRegionReplicaSet(),
+                                    dataRegionCreateTask.getStorageGroup()));
+                            createDataRegionHandler.putNodeLocation(
+                                dataRegionCreateTask.getRegionId().getId(),
+                                dataRegionCreateTask.getTargetDataNode());
+                          }
+
+                          
CnToDnInternalServiceAsyncRequestManager.getInstance()
+                              
.sendAsyncRequestWithRetry(createDataRegionHandler);
+
+                          for (Map.Entry<Integer, TSStatus> entry :
+                              
createDataRegionHandler.getResponseMap().entrySet()) {
+                            if (entry.getValue().getCode()
+                                == 
TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+                              successfulTask.add(
+                                  new TConsensusGroupId(
+                                      TConsensusGroupType.DataRegion, 
entry.getKey()));
+                            }
+                          }
+                          break;
+                      }
+                      break;
+                    case DELETE:
+                      // delete region
+                      DataNodeAsyncRequestContext<TConsensusGroupId, TSStatus> 
deleteRegionHandler =
+                          new 
DataNodeAsyncRequestContext<>(CnToDnAsyncRequestType.DELETE_REGION);
+                      Map<Integer, TConsensusGroupId> regionIdMap = new 
HashMap<>();
+                      for (RegionMaintainTask regionMaintainTask : 
selectedRegionMaintainTask) {
+                        RegionDeleteTask regionDeleteTask = (RegionDeleteTask) 
regionMaintainTask;
+                        LOGGER.info(
+                            ManagerMessages.START_TO_DELETE_REGION_ON_DATANODE,
+                            regionDeleteTask.getRegionId(),
+                            regionDeleteTask.getTargetDataNode());
+                        deleteRegionHandler.putRequest(
+                            regionDeleteTask.getRegionId().getId(), 
regionDeleteTask.getRegionId());
+                        deleteRegionHandler.putNodeLocation(
+                            regionDeleteTask.getRegionId().getId(),
+                            regionDeleteTask.getTargetDataNode());
+                        regionIdMap.put(
+                            regionDeleteTask.getRegionId().getId(), 
regionDeleteTask.getRegionId());
+                      }
+
+                      long startTime = System.currentTimeMillis();
+                      CnToDnInternalServiceAsyncRequestManager.getInstance()
+                          .sendAsyncRequestWithRetry(deleteRegionHandler);
+
+                      LOGGER.info(
+                          ManagerMessages.DELETING_REGIONS_COSTS_MS,
+                          (System.currentTimeMillis() - startTime));
+
+                      for (Map.Entry<Integer, TSStatus> entry :
+                          deleteRegionHandler.getResponseMap().entrySet()) {
+                        if (entry.getValue().getCode()
+                            == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+                          successfulTask.add(regionIdMap.get(entry.getKey()));
+                        }
+                      }
+                      break;
+                  }
 
-      // Durably remove the head of every successfully created region from the 
persisted queue.
-      try {
-        getConsensusManager().write(new 
PollSpecificRegionMaintainTaskPlan(successfulRegions));
-      } catch (ConsensusException e) {
-        LOGGER.warn(CONSENSUS_WRITE_ERROR, e);
-      }
+                  if (successfulTask.isEmpty()) {
+                    break;
+                  }
 
-      if (successfulRegions.size() < selectedCount) {
-        // Some tasks failed this round; stop and retry on the next schedule 
so that the tasks of
-        // each region keep being executed in the order they were offered.
-        break;
-      }
-    }
-  }
+                  for (TConsensusGroupId regionId : successfulTask) {
+                    regionMaintainTaskMap.compute(
+                        regionId,
+                        (k, v) -> {
+                          if (v == null) {
+                            throw new IllegalStateException();
+                          }
+                          v.poll();
+                          if (v.isEmpty()) {
+                            return null;
+                          } else {
+                            return v;
+                          }
+                        });
+                  }
 
-  /**
-   * Send a batched create RPC for the given heads, all of which share the 
given region type, and
-   * return the ids of the regions whose replica was created successfully.
-   */
-  private Set<TConsensusGroupId> submitRegionCreateTasks(
-      TConsensusGroupType regionType, List<RegionCreateTask> createTasks) {
-    final Set<TConsensusGroupId> successfulRegions = new HashSet<>();
-    switch (regionType) {
-      case SchemaRegion:
-        final DataNodeAsyncRequestContext<TCreateSchemaRegionReq, TSStatus> 
schemaHandler =
-            new 
DataNodeAsyncRequestContext<>(CnToDnAsyncRequestType.CREATE_SCHEMA_REGION);
-        for (RegionCreateTask task : createTasks) {
-          LOGGER.info(
-              ManagerMessages.START_TO_CREATE_REGION_ON_DATANODE,
-              task.getRegionReplicaSet().getRegionId(),
-              task.getTargetDataNode());
-          schemaHandler.putRequest(
-              task.getRegionId().getId(),
-              new TCreateSchemaRegionReq(task.getRegionReplicaSet(), 
task.getStorageGroup()));
-          schemaHandler.putNodeLocation(task.getRegionId().getId(), 
task.getTargetDataNode());
-        }
-        CnToDnInternalServiceAsyncRequestManager.getInstance()
-            .sendAsyncRequestWithRetry(schemaHandler);
-        collectSuccessfulRegions(
-            schemaHandler.getResponseMap(), TConsensusGroupType.SchemaRegion, 
successfulRegions);
-        break;
-      case DataRegion:
-        final DataNodeAsyncRequestContext<TCreateDataRegionReq, TSStatus> 
dataHandler =
-            new 
DataNodeAsyncRequestContext<>(CnToDnAsyncRequestType.CREATE_DATA_REGION);
-        for (RegionCreateTask task : createTasks) {
-          LOGGER.info(
-              ManagerMessages.START_TO_CREATE_REGION_ON_DATANODE,
-              task.getRegionReplicaSet().getRegionId(),
-              task.getTargetDataNode());
-          dataHandler.putRequest(
-              task.getRegionId().getId(),
-              new TCreateDataRegionReq(task.getRegionReplicaSet(), 
task.getStorageGroup()));
-          dataHandler.putNodeLocation(task.getRegionId().getId(), 
task.getTargetDataNode());
-        }
-        CnToDnInternalServiceAsyncRequestManager.getInstance()
-            .sendAsyncRequestWithRetry(dataHandler);
-        collectSuccessfulRegions(
-            dataHandler.getResponseMap(), TConsensusGroupType.DataRegion, 
successfulRegions);
-        break;
-      default:
-        break;
-    }
-    return successfulRegions;
-  }
+                  // Poll the head entry if success
+                  try {
+                    getConsensusManager()
+                        .write(new 
PollSpecificRegionMaintainTaskPlan(successfulTask));
+                  } catch (ConsensusException e) {
+                    LOGGER.warn(CONSENSUS_WRITE_ERROR, e);
+                  }
 
-  private void collectSuccessfulRegions(
-      Map<Integer, TSStatus> responseMap,
-      TConsensusGroupType regionType,
-      Set<TConsensusGroupId> successfulRegions) {
-    for (Map.Entry<Integer, TSStatus> entry : responseMap.entrySet()) {
-      if (entry.getValue().getCode() == 
TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
-        successfulRegions.add(new TConsensusGroupId(regionType, 
entry.getKey()));
-      }
-    }
+                  if (successfulTask.size() < 
selectedRegionMaintainTask.size()) {
+                    // Here we just break and wait until next schedule task
+                    // due to all the RegionMaintainEntry should be executed by
+                    // the order of they were offered
+                    break;
+                  }
+                }
+              }
+            });
   }
 
   public void startRegionCleaner() {
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/partition/PartitionInfo.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/partition/PartitionInfo.java
index da2466c1e24..8b2079b581d 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/partition/PartitionInfo.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/partition/PartitionInfo.java
@@ -64,7 +64,6 @@ import 
org.apache.iotdb.confignode.consensus.response.partition.SchemaPartitionR
 import org.apache.iotdb.confignode.exception.DatabaseNotExistsException;
 import org.apache.iotdb.confignode.i18n.ConfigNodeMessages;
 import 
org.apache.iotdb.confignode.persistence.partition.maintainer.RegionMaintainTask;
-import 
org.apache.iotdb.confignode.persistence.partition.maintainer.RegionMaintainType;
 import org.apache.iotdb.confignode.rpc.thrift.TRegionInfo;
 import org.apache.iotdb.confignode.rpc.thrift.TShowRegionReq;
 import org.apache.iotdb.confignode.rpc.thrift.TTimeSlotList;
@@ -233,20 +232,7 @@ public class PartitionInfo implements SnapshotProcessor {
   public TSStatus offerRegionMaintainTasks(
       OfferRegionMaintainTasksPlan offerRegionMaintainTasksPlan) {
     synchronized (regionMaintainTaskList) {
-      // The RegionMaintainer queue only recreates failed region replicas now; 
region deletion is
-      // owned by RemoveRegionGroupProcedure. Drop any legacy DELETE task that 
an upgraded node may
-      // replay from an old consensus log, so it cannot get stuck in the queue 
and block the
-      // recreation of that region's other replicas.
-      for (RegionMaintainTask task : 
offerRegionMaintainTasksPlan.getRegionMaintainTaskList()) {
-        if (RegionMaintainType.DELETE.equals(task.getType())) {
-          LOGGER.info(
-              ConfigNodeMessages
-                  
.MESSAGE_DROPPING_LEGACY_REGION_DELETE_TASK_FOR_ARG_WHILE_REPLAYING_OFFER_PLAN_REGION_DELETION_IS_NOW_HANDLED_BY_REMOVEREGIONGROUPPROCEDURE_2A81A649,
-              task.getRegionId());
-          continue;
-        }
-        regionMaintainTaskList.add(task);
-      }
+      
regionMaintainTaskList.addAll(offerRegionMaintainTasksPlan.getRegionMaintainTaskList());
       return RpcUtils.SUCCESS_STATUS;
     }
   }
@@ -1088,22 +1074,11 @@ public class PartitionInfo implements SnapshotProcessor 
{
         databasePartitionTables.put(database, databasePartitionTable);
       }
 
-      // restore the RegionMaintainer queue
+      // restore deletedRegionSet
       length = ReadWriteIOUtils.readInt(fileInputStream);
       for (int i = 0; i < length; i++) {
         final RegionMaintainTask task =
             RegionMaintainTask.Factory.create(fileInputStream, protocol);
-        // The RegionMaintainer queue only recreates failed region replicas 
now; region deletion is
-        // owned by RemoveRegionGroupProcedure. Drop any legacy DELETE task 
carried over from an
-        // upgraded snapshot so it cannot get stuck at the head of a region's 
queue and block the
-        // recreation of that region's other replicas.
-        if (RegionMaintainType.DELETE.equals(task.getType())) {
-          LOGGER.info(
-              ConfigNodeMessages
-                  
.MESSAGE_DROPPING_LEGACY_REGION_DELETE_TASK_FOR_ARG_WHILE_LOADING_SNAPSHOT_REGION_DELETION_IS_NOW_HANDLED_BY_REMOVEREGIONGROUPPROCEDURE_A9D409A0,
-              task.getRegionId());
-          continue;
-        }
         regionMaintainTaskList.add(task);
       }
     }
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/region/CreateRegionGroupsProcedure.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/region/CreateRegionGroupsProcedure.java
index cb26afc97dd..e9cce807e77 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/region/CreateRegionGroupsProcedure.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/region/CreateRegionGroupsProcedure.java
@@ -36,6 +36,7 @@ import org.apache.iotdb.confignode.i18n.ConfigNodeMessages;
 import org.apache.iotdb.confignode.i18n.ProcedureMessages;
 import 
org.apache.iotdb.confignode.manager.load.cache.region.RegionHeartbeatSample;
 import 
org.apache.iotdb.confignode.persistence.partition.maintainer.RegionCreateTask;
+import 
org.apache.iotdb.confignode.persistence.partition.maintainer.RegionDeleteTask;
 import org.apache.iotdb.confignode.procedure.env.ConfigNodeProcedureEnv;
 import org.apache.iotdb.confignode.procedure.exception.ProcedureException;
 import org.apache.iotdb.confignode.procedure.impl.StateMachineProcedure;
@@ -50,9 +51,7 @@ import org.slf4j.LoggerFactory;
 import java.io.DataOutputStream;
 import java.io.IOException;
 import java.nio.ByteBuffer;
-import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
@@ -108,9 +107,6 @@ public class CreateRegionGroupsProcedure
       case SHUNT_REGION_REPLICAS:
         persistPlan = new CreateRegionGroupsPlan();
         final OfferRegionMaintainTasksPlan offerPlan = new 
OfferRegionMaintainTasksPlan();
-        // RegionGroups that failed to reach a serving quorum are removed via 
a child
-        // RemoveRegionGroupProcedure, which deletes every replica that did 
get created.
-        final List<RemoveRegionGroupProcedure> removeRegionGroupProcedures = 
new ArrayList<>();
         // Filter those RegionGroups that created successfully
         createRegionGroupsPlan
             .getRegionGroupMap()
@@ -158,11 +154,7 @@ public class CreateRegionGroupsProcedure
                                       
.CREATEREGIONGROUPS_FAILED_TO_CREATE_SOME_REPLICAS_OF_REGIONGROUP_BUT_THIS,
                                   regionReplicaSet.getRegionId());
                             } else {
-                              // The redundant RegionReplicas (the ones that 
did get created) should
-                              // be deleted otherwise
-                              final TRegionReplicaSet redundantReplicas =
-                                  new TRegionReplicaSet()
-                                      
.setRegionId(regionReplicaSet.getRegionId());
+                              // The redundant RegionReplicas should be 
deleted otherwise
                               regionReplicaSet
                                   .getDataNodeLocations()
                                   .forEach(
@@ -170,13 +162,12 @@ public class CreateRegionGroupsProcedure
                                         if (!failedRegionReplicas
                                             .getDataNodeLocations()
                                             .contains(targetDataNode)) {
-                                          
redundantReplicas.addToDataNodeLocations(targetDataNode);
+                                          RegionDeleteTask deleteTask =
+                                              new RegionDeleteTask(
+                                                  targetDataNode, 
regionReplicaSet.getRegionId());
+                                          
offerPlan.appendRegionMaintainTask(deleteTask);
                                         }
                                       });
-                              if (redundantReplicas.getDataNodeLocationsSize() 
> 0) {
-                                removeRegionGroupProcedures.add(
-                                    new 
RemoveRegionGroupProcedure(redundantReplicas));
-                              }
 
                               LOGGER.info(
                                   ProcedureMessages
@@ -197,7 +188,6 @@ public class CreateRegionGroupsProcedure
           LOGGER.warn(
               
ConfigNodeMessages.FAILED_IN_THE_WRITE_API_EXECUTING_THE_CONSENSUS_LAYER_DUE, 
e);
         }
-        removeRegionGroupProcedures.forEach(this::addChildProcedure);
         setNextState(CreateRegionGroupsState.REBALANCE_DATA_PARTITION_POLICY);
         break;
       case REBALANCE_DATA_PARTITION_POLICY:
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/region/RemoveRegionGroupProcedure.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/region/RemoveRegionGroupProcedure.java
deleted file mode 100644
index 2dd2e0d6dd3..00000000000
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/region/RemoveRegionGroupProcedure.java
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * 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.iotdb.confignode.procedure.impl.region;
-
-import org.apache.iotdb.common.rpc.thrift.TDataNodeLocation;
-import org.apache.iotdb.common.rpc.thrift.TRegionReplicaSet;
-import org.apache.iotdb.common.rpc.thrift.TSStatus;
-import org.apache.iotdb.commons.exception.runtime.ThriftSerDeException;
-import org.apache.iotdb.commons.queryengine.utils.DateTimeUtils;
-import org.apache.iotdb.commons.utils.CommonDateTimeUtils;
-import org.apache.iotdb.commons.utils.TestOnly;
-import org.apache.iotdb.commons.utils.ThriftCommonsSerDeUtils;
-import org.apache.iotdb.confignode.i18n.ProcedureMessages;
-import org.apache.iotdb.confignode.procedure.env.ConfigNodeProcedureEnv;
-import org.apache.iotdb.confignode.procedure.env.RegionMaintainHandler;
-import org.apache.iotdb.confignode.procedure.exception.ProcedureException;
-import org.apache.iotdb.confignode.procedure.state.RemoveRegionGroupState;
-import org.apache.iotdb.confignode.procedure.store.ProcedureType;
-import org.apache.iotdb.mpp.rpc.thrift.TRegionMigrateResult;
-
-import org.apache.tsfile.utils.ReadWriteIOUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.util.List;
-import java.util.Objects;
-import java.util.stream.Collectors;
-
-import static org.apache.iotdb.commons.utils.KillPoint.KillPoint.setKillPoint;
-import static 
org.apache.iotdb.confignode.procedure.env.RegionMaintainHandler.simplifiedLocation;
-import static org.apache.iotdb.rpc.TSStatusCode.SUCCESS_STATUS;
-
-/**
- * Delete a whole region group: every replica's consensus peer and all of its 
data on every DataNode
- * that hosts it.
- *
- * <p>Each replica is removed with a local {@code deleteLocalPeer} (the {@code
- * submitDeleteOldRegionPeerTask} path), which needs no consensus quorum and 
tolerates an
- * already-absent peer, so it works for a group of any size — including a 
sub-quorum group that
- * never finished forming. The DataNode runs the deletion asynchronously and 
this procedure polls
- * for the result, so a slow deletion is never wrongly reported as finished.
- */
-public class RemoveRegionGroupProcedure extends 
RegionOperationProcedure<RemoveRegionGroupState> {
-  private static final Logger LOGGER = 
LoggerFactory.getLogger(RemoveRegionGroupProcedure.class);
-
-  private static final int MAX_DELETE_REPLICA_RETRY = 3;
-  private static final long DELETE_REPLICA_RETRY_INTERVAL_MS = 5_000;
-
-  private TRegionReplicaSet regionReplicaSet;
-
-  // The index of the replica currently being deleted. Persisted and advanced 
only after that
-  // replica
-  // is deleted, so after a ConfigNode leader change the procedure resumes on 
the first replica it
-  // has
-  // not finished deleting.
-  private int currentReplicaIndex;
-
-  // Number of failed attempts on the replica at currentReplicaIndex. 
Transient: a leader change
-  // restarts the retry budget for the current replica.
-  private transient int attemptedForCurrentReplica;
-
-  public RemoveRegionGroupProcedure() {
-    super();
-  }
-
-  public RemoveRegionGroupProcedure(TRegionReplicaSet regionReplicaSet) {
-    super(regionReplicaSet.getRegionId());
-    this.regionReplicaSet = regionReplicaSet;
-  }
-
-  @TestOnly
-  void setCurrentReplicaIndex(int currentReplicaIndex) {
-    this.currentReplicaIndex = currentReplicaIndex;
-  }
-
-  @Override
-  protected Flow executeFromState(ConfigNodeProcedureEnv env, 
RemoveRegionGroupState state)
-      throws InterruptedException {
-    final List<TDataNodeLocation> dataNodeLocations =
-        regionReplicaSet == null ? null : 
regionReplicaSet.getDataNodeLocations();
-    if (dataNodeLocations == null) {
-      // A null replica set means deserialization failed; fail loudly instead 
of silently reporting
-      // the group as deleted, otherwise the parent would drop the partition 
table while the region
-      // data is still on disk.
-      setFailure(
-          new ProcedureException(ProcedureMessages.UNSUPPORTED_STATE + 
"missing regionReplicaSet"));
-      return Flow.NO_MORE_STATE;
-    }
-    final RegionMaintainHandler handler = env.getRegionMaintainHandler();
-    switch (state) {
-      case DELETE_REGION_REPLICAS:
-        if (currentReplicaIndex == 0 && attemptedForCurrentReplica == 0) {
-          LOGGER.info(
-              ProcedureMessages.PID_REMOVEREGIONGROUP_STARTED_WILL_BE_DELETED,
-              getProcId(),
-              regionId,
-              dataNodeLocations.stream()
-                  .map(RegionMaintainHandler::simplifiedLocation)
-                  .collect(Collectors.toList()));
-        }
-        if (currentReplicaIndex >= dataNodeLocations.size()) {
-          // Requirement: every successfully completed maintain task must be 
logged.
-          LOGGER.info(
-              ProcedureMessages.PID_REMOVEREGIONGROUP_SUCCESS_PROCEDURE_TOOK,
-              getProcId(),
-              regionId,
-              CommonDateTimeUtils.convertMillisecondToDurationStr(
-                  System.currentTimeMillis() - getSubmittedTime()),
-              DateTimeUtils.convertLongToDate(getSubmittedTime(), "ms"));
-          return Flow.NO_MORE_STATE;
-        }
-
-        final TDataNodeLocation targetDataNode = 
dataNodeLocations.get(currentReplicaIndex);
-        LOGGER.info(
-            
ProcedureMessages.PID_REMOVEREGIONGROUP_STARTED_REPLICA_WILL_BE_DELETED_FROM_DATANODE,
-            getProcId(),
-            regionId,
-            simplifiedLocation(targetDataNode));
-
-        // deleteLocalPeer is idempotent (it tolerates an already-absent peer) 
and the DataNode
-        // dedups by taskId, so re-submitting after a leader change or a retry 
is safe.
-        final TSStatus submitStatus;
-        final TRegionMigrateResult result;
-        try {
-          submitStatus =
-              handler.submitDeleteOldRegionPeerTask(getProcId(), 
targetDataNode, regionId);
-          setKillPoint(state);
-          if (submitStatus.getCode() != SUCCESS_STATUS.getStatusCode()) {
-            return retryCurrentReplicaOrFail(
-                String.format(
-                    "submit delete task for region %s to DataNode %s failed: 
%s",
-                    regionId, simplifiedLocation(targetDataNode), 
submitStatus));
-          }
-          result = handler.waitTaskFinish(getProcId(), targetDataNode);
-        } catch (InterruptedException e) {
-          throw e;
-        } catch (Exception e) {
-          LOGGER.error(ProcedureMessages.PID_REMOVEREGIONGROUP_STATE_FAILED, 
getProcId(), state, e);
-          return retryCurrentReplicaOrFail(
-              String.format(
-                  "delete region %s from DataNode %s threw %s",
-                  regionId, simplifiedLocation(targetDataNode), e));
-        }
-
-        switch (result.getTaskStatus()) {
-          case SUCCESS:
-            // Advance to the next replica with a fresh retry budget.
-            currentReplicaIndex++;
-            attemptedForCurrentReplica = 0;
-            setNextState(RemoveRegionGroupState.DELETE_REGION_REPLICAS);
-            return Flow.HAS_MORE_STATE;
-          case PROCESSING:
-            // waitTaskFinish() only returns PROCESSING when its polling loop 
was interrupted, i.e.
-            // this ConfigNode is shutting down / losing leadership. The 
delete task is still
-            // running
-            // on the DataNode, so persist and re-poll after recovery: stay on 
this replica without
-            // advancing it and without consuming a retry attempt.
-            setNextState(RemoveRegionGroupState.DELETE_REGION_REPLICAS);
-            return Flow.HAS_MORE_STATE;
-          case TASK_NOT_EXIST:
-          case FAIL:
-          default:
-            return retryCurrentReplicaOrFail(
-                String.format(
-                    "delete region %s from DataNode %s, task status is %s",
-                    regionId, simplifiedLocation(targetDataNode), 
result.getTaskStatus()));
-        }
-      default:
-        setFailure(new ProcedureException(ProcedureMessages.UNSUPPORTED_STATE 
+ state.name()));
-        return Flow.NO_MORE_STATE;
-    }
-  }
-
-  /**
-   * Retry the replica at {@link #currentReplicaIndex} after a backoff, or 
fail the whole procedure
-   * once the per-replica retry budget is exhausted. Failing (rather than 
skipping the replica)
-   * keeps the parent from dropping the partition table while a region's 
peer/data is still on disk.
-   */
-  private Flow retryCurrentReplicaOrFail(String reason) throws 
InterruptedException {
-    attemptedForCurrentReplica++;
-    if (attemptedForCurrentReplica <= MAX_DELETE_REPLICA_RETRY) {
-      LOGGER.warn(
-          ProcedureMessages.PID_REMOVEREGIONGROUP_DELETE_REPLICA_FAILED,
-          getProcId(),
-          regionId,
-          attemptedForCurrentReplica,
-          MAX_DELETE_REPLICA_RETRY + 1,
-          reason);
-      Thread.sleep(DELETE_REPLICA_RETRY_INTERVAL_MS);
-      setNextState(RemoveRegionGroupState.DELETE_REGION_REPLICAS);
-      return Flow.HAS_MORE_STATE;
-    }
-    setFailure(
-        new ProcedureException(
-            String.format(
-                "[pid%d][RemoveRegionGroup] gave up after %d attempts: %s",
-                getProcId(), attemptedForCurrentReplica, reason)));
-    return Flow.NO_MORE_STATE;
-  }
-
-  @Override
-  protected void rollbackState(ConfigNodeProcedureEnv env, 
RemoveRegionGroupState state)
-      throws IOException, InterruptedException, ProcedureException {}
-
-  @Override
-  protected RemoveRegionGroupState getState(int stateId) {
-    return RemoveRegionGroupState.values()[stateId];
-  }
-
-  @Override
-  protected int getStateId(RemoveRegionGroupState removeRegionGroupState) {
-    return removeRegionGroupState.ordinal();
-  }
-
-  @Override
-  protected RemoveRegionGroupState getInitialState() {
-    return RemoveRegionGroupState.DELETE_REGION_REPLICAS;
-  }
-
-  @Override
-  public void serialize(DataOutputStream stream) throws IOException {
-    
stream.writeShort(ProcedureType.REMOVE_REGION_GROUP_PROCEDURE.getTypeCode());
-    super.serialize(stream);
-    ThriftCommonsSerDeUtils.serializeTRegionReplicaSet(regionReplicaSet, 
stream);
-    ReadWriteIOUtils.write(currentReplicaIndex, stream);
-  }
-
-  @Override
-  public void deserialize(ByteBuffer byteBuffer) {
-    super.deserialize(byteBuffer);
-    try {
-      regionReplicaSet = 
ThriftCommonsSerDeUtils.deserializeTRegionReplicaSet(byteBuffer);
-      regionId = regionReplicaSet.getRegionId();
-      currentReplicaIndex = ReadWriteIOUtils.readInt(byteBuffer);
-    } catch (ThriftSerDeException e) {
-      LOGGER.error(ProcedureMessages.ERROR_IN_DESERIALIZE, this.getClass(), e);
-    }
-  }
-
-  @Override
-  public boolean equals(Object obj) {
-    if (!(obj instanceof RemoveRegionGroupProcedure)) {
-      return false;
-    }
-    RemoveRegionGroupProcedure procedure = (RemoveRegionGroupProcedure) obj;
-    return this.currentReplicaIndex == procedure.currentReplicaIndex
-        && Objects.equals(this.regionReplicaSet, procedure.regionReplicaSet);
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(regionReplicaSet, currentReplicaIndex);
-  }
-
-  @Override
-  public String toString() {
-    return "RemoveRegionGroupProcedure{"
-        + "regionReplicaSet="
-        + regionReplicaSet
-        + ", currentReplicaIndex="
-        + currentReplicaIndex
-        + '}';
-  }
-}
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/DeleteDatabaseProcedure.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/DeleteDatabaseProcedure.java
index 84309e33fb5..7a10483a6bf 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/DeleteDatabaseProcedure.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/DeleteDatabaseProcedure.java
@@ -19,21 +19,29 @@
 
 package org.apache.iotdb.confignode.procedure.impl.schema;
 
+import org.apache.iotdb.common.rpc.thrift.TConsensusGroupId;
+import org.apache.iotdb.common.rpc.thrift.TConsensusGroupType;
+import org.apache.iotdb.common.rpc.thrift.TDataNodeLocation;
 import org.apache.iotdb.common.rpc.thrift.TRegionReplicaSet;
 import org.apache.iotdb.common.rpc.thrift.TSStatus;
 import org.apache.iotdb.commons.exception.runtime.ThriftSerDeException;
 import org.apache.iotdb.commons.service.metric.MetricService;
 import org.apache.iotdb.commons.utils.ThriftConfigNodeSerDeUtils;
+import org.apache.iotdb.confignode.client.async.CnToDnAsyncRequestType;
+import 
org.apache.iotdb.confignode.client.async.CnToDnInternalServiceAsyncRequestManager;
+import 
org.apache.iotdb.confignode.client.async.handlers.DataNodeAsyncRequestContext;
 import 
org.apache.iotdb.confignode.consensus.request.write.database.PreDeleteDatabasePlan;
+import 
org.apache.iotdb.confignode.consensus.request.write.region.OfferRegionMaintainTasksPlan;
 import org.apache.iotdb.confignode.i18n.ProcedureMessages;
 import org.apache.iotdb.confignode.manager.partition.PartitionMetrics;
+import 
org.apache.iotdb.confignode.persistence.partition.maintainer.RegionDeleteTask;
 import org.apache.iotdb.confignode.procedure.env.ConfigNodeProcedureEnv;
 import org.apache.iotdb.confignode.procedure.exception.ProcedureException;
 import org.apache.iotdb.confignode.procedure.impl.StateMachineProcedure;
-import 
org.apache.iotdb.confignode.procedure.impl.region.RemoveRegionGroupProcedure;
 import org.apache.iotdb.confignode.procedure.state.schema.DeleteDatabaseState;
 import org.apache.iotdb.confignode.procedure.store.ProcedureType;
 import org.apache.iotdb.confignode.rpc.thrift.TDatabaseSchema;
+import org.apache.iotdb.consensus.exception.ConsensusException;
 import org.apache.iotdb.rpc.TSStatusCode;
 
 import org.apache.thrift.TException;
@@ -43,7 +51,10 @@ import org.slf4j.LoggerFactory;
 import java.io.DataOutputStream;
 import java.io.IOException;
 import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 
 public class DeleteDatabaseProcedure
@@ -104,23 +115,86 @@ public class DeleteDatabaseProcedure
               
ProcedureMessages.LOG_DELETEDATABASEPROCEDURE_DELETE_DATABASESCHEMA_ARG_A49A47AC,
               deleteDatabaseSchema.getName());
 
-          // Delete every region group (both schema and data regions) of this 
database via a
-          // RemoveRegionGroupProcedure child. The DatabasePartitionTable 
(handled in the next
-          // state) is only removed once these children have finished, so a 
slow region deletion is
-          // always completed before the coordinator forgets about it.
+          // Submit RegionDeleteTasks
+          final OfferRegionMaintainTasksPlan dataRegionDeleteTaskOfferPlan =
+              new OfferRegionMaintainTasksPlan();
           final List<TRegionReplicaSet> regionReplicaSets =
               env.getAllReplicaSets(deleteDatabaseSchema.getName());
+          final List<TRegionReplicaSet> schemaRegionReplicaSets = new 
ArrayList<>();
           regionReplicaSets.forEach(
               regionReplicaSet -> {
                 // Clear heartbeat cache along the way
                 env.getConfigManager()
                     .getLoadManager()
                     
.removeRegionGroupRelatedCache(regionReplicaSet.getRegionId());
-                addChildProcedure(new 
RemoveRegionGroupProcedure(regionReplicaSet));
+
+                if (regionReplicaSet
+                    .getRegionId()
+                    .getType()
+                    .equals(TConsensusGroupType.SchemaRegion)) {
+                  schemaRegionReplicaSets.add(regionReplicaSet);
+                } else {
+                  regionReplicaSet
+                      .getDataNodeLocations()
+                      .forEach(
+                          targetDataNode ->
+                              
dataRegionDeleteTaskOfferPlan.appendRegionMaintainTask(
+                                  new RegionDeleteTask(
+                                      targetDataNode, 
regionReplicaSet.getRegionId())));
+                }
               });
-          setNextState(DeleteDatabaseState.DELETE_DATABASE_CONFIG);
-          break;
-        case DELETE_DATABASE_CONFIG:
+
+          if 
(!dataRegionDeleteTaskOfferPlan.getRegionMaintainTaskList().isEmpty()) {
+            // submit async data region delete task
+            
env.getConfigManager().getConsensusManager().write(dataRegionDeleteTaskOfferPlan);
+          }
+
+          // try sync delete schemaengine region
+          final DataNodeAsyncRequestContext<TConsensusGroupId, TSStatus> 
asyncClientHandler =
+              new 
DataNodeAsyncRequestContext<>(CnToDnAsyncRequestType.DELETE_REGION);
+          final Map<Integer, RegionDeleteTask> schemaRegionDeleteTaskMap = new 
HashMap<>();
+          int requestIndex = 0;
+          for (final TRegionReplicaSet schemaRegionReplicaSet : 
schemaRegionReplicaSets) {
+            for (final TDataNodeLocation dataNodeLocation :
+                schemaRegionReplicaSet.getDataNodeLocations()) {
+              asyncClientHandler.putRequest(requestIndex, 
schemaRegionReplicaSet.getRegionId());
+              asyncClientHandler.putNodeLocation(requestIndex, 
dataNodeLocation);
+              schemaRegionDeleteTaskMap.put(
+                  requestIndex,
+                  new RegionDeleteTask(dataNodeLocation, 
schemaRegionReplicaSet.getRegionId()));
+              requestIndex++;
+            }
+          }
+          if (!schemaRegionDeleteTaskMap.isEmpty()) {
+            CnToDnInternalServiceAsyncRequestManager.getInstance()
+                .sendAsyncRequestWithRetry(asyncClientHandler);
+            for (final Map.Entry<Integer, TSStatus> entry :
+                asyncClientHandler.getResponseMap().entrySet()) {
+              if (entry.getValue().getCode() == 
TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+                LOG.info(
+                    "[DeleteDatabaseProcedure] Successfully delete 
SchemaRegion[{}] on {}",
+                    asyncClientHandler.getRequest(entry.getKey()),
+                    
schemaRegionDeleteTaskMap.get(entry.getKey()).getTargetDataNode());
+                schemaRegionDeleteTaskMap.remove(entry.getKey());
+              } else {
+                LOG.warn(
+                    "[DeleteDatabaseProcedure] Failed to delete 
SchemaRegion[{}] on {}. Submit to async deletion.",
+                    asyncClientHandler.getRequest(entry.getKey()),
+                    
schemaRegionDeleteTaskMap.get(entry.getKey()).getTargetDataNode());
+              }
+            }
+
+            if (!schemaRegionDeleteTaskMap.isEmpty()) {
+              // submit async schemaengine region delete task for failed sync 
execution
+              final OfferRegionMaintainTasksPlan 
schemaRegionDeleteTaskOfferPlan =
+                  new OfferRegionMaintainTasksPlan();
+              schemaRegionDeleteTaskMap
+                  .values()
+                  
.forEach(schemaRegionDeleteTaskOfferPlan::appendRegionMaintainTask);
+              
env.getConfigManager().getConsensusManager().write(schemaRegionDeleteTaskOfferPlan);
+            }
+          }
+
           env.getConfigManager()
               .getLoadManager()
               .clearDataPartitionPolicyTable(deleteDatabaseSchema.getName());
@@ -151,7 +225,7 @@ public class DeleteDatabaseProcedure
                     
ProcedureMessages.DELETEDATABASEPROCEDURE_DELETE_DATABASESCHEMA_FAILED));
           }
       }
-    } catch (final TException | IOException e) {
+    } catch (final ConsensusException | TException | IOException e) {
       if (isRollbackSupported(state)) {
         setFailure(
             new ProcedureException(
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/state/RemoveRegionGroupState.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/state/RemoveRegionGroupState.java
deleted file mode 100644
index 9b7d99c8a23..00000000000
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/state/RemoveRegionGroupState.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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.iotdb.confignode.procedure.state;
-
-public enum RemoveRegionGroupState {
-  DELETE_REGION_REPLICAS,
-}
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/state/schema/DeleteDatabaseState.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/state/schema/DeleteDatabaseState.java
index c0ad67fe811..cde6b2bdd81 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/state/schema/DeleteDatabaseState.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/state/schema/DeleteDatabaseState.java
@@ -22,8 +22,5 @@ package org.apache.iotdb.confignode.procedure.state.schema;
 public enum DeleteDatabaseState {
   PRE_DELETE_DATABASE,
   INVALIDATE_CACHE,
-  DELETE_DATABASE_SCHEMA,
-  // Delete the DatabasePartitionTable and related config after all region 
groups have been deleted
-  // by the RemoveRegionGroupProcedure children spawned in 
DELETE_DATABASE_SCHEMA.
-  DELETE_DATABASE_CONFIG
+  DELETE_DATABASE_SCHEMA
 }
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/store/ProcedureFactory.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/store/ProcedureFactory.java
index aadc40f310c..165b048b636 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/store/ProcedureFactory.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/store/ProcedureFactory.java
@@ -43,7 +43,6 @@ import 
org.apache.iotdb.confignode.procedure.impl.region.CreateRegionGroupsProce
 import 
org.apache.iotdb.confignode.procedure.impl.region.NotifyRegionMigrationProcedure;
 import 
org.apache.iotdb.confignode.procedure.impl.region.ReconstructRegionProcedure;
 import 
org.apache.iotdb.confignode.procedure.impl.region.RegionMigrateProcedure;
-import 
org.apache.iotdb.confignode.procedure.impl.region.RemoveRegionGroupProcedure;
 import 
org.apache.iotdb.confignode.procedure.impl.region.RemoveRegionPeerProcedure;
 import 
org.apache.iotdb.confignode.procedure.impl.schema.AlterEncodingCompressorProcedure;
 import 
org.apache.iotdb.confignode.procedure.impl.schema.AlterLogicalViewProcedure;
@@ -146,9 +145,6 @@ public class ProcedureFactory implements IProcedureFactory {
       case NOTIFY_REGION_MIGRATION_PROCEDURE:
         procedure = new NotifyRegionMigrationProcedure();
         break;
-      case REMOVE_REGION_GROUP_PROCEDURE:
-        procedure = new RemoveRegionGroupProcedure();
-        break;
       case ALTER_ENCODING_COMPRESSOR_PROCEDURE:
         procedure = new AlterEncodingCompressorProcedure(false);
         break;
@@ -470,8 +466,6 @@ public class ProcedureFactory implements IProcedureFactory {
       return ProcedureType.RECONSTRUCT_REGION_PROCEDURE;
     } else if (procedure instanceof NotifyRegionMigrationProcedure) {
       return ProcedureType.NOTIFY_REGION_MIGRATION_PROCEDURE;
-    } else if (procedure instanceof RemoveRegionGroupProcedure) {
-      return ProcedureType.REMOVE_REGION_GROUP_PROCEDURE;
     } else if (procedure instanceof CreateTriggerProcedure) {
       return ProcedureType.CREATE_TRIGGER_PROCEDURE;
     } else if (procedure instanceof DropTriggerProcedure) {
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/store/ProcedureType.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/store/ProcedureType.java
index c29d1afd672..75299638b60 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/store/ProcedureType.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/store/ProcedureType.java
@@ -41,7 +41,6 @@ public enum ProcedureType {
   ADD_REGION_PEER_PROCEDURE((short) 204),
   REMOVE_REGION_PEER_PROCEDURE((short) 205),
   NOTIFY_REGION_MIGRATION_PROCEDURE((short) 206),
-  REMOVE_REGION_GROUP_PROCEDURE((short) 207),
   @TestOnly
   CREATE_MANY_DATABASES_PROCEDURE((short) 250),
 
diff --git 
a/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/persistence/PartitionInfoTest.java
 
b/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/persistence/PartitionInfoTest.java
index 8c32378cfcb..afccb0c0eba 100644
--- 
a/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/persistence/PartitionInfoTest.java
+++ 
b/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/persistence/PartitionInfoTest.java
@@ -40,8 +40,6 @@ import 
org.apache.iotdb.confignode.consensus.response.partition.RegionInfoListRe
 import org.apache.iotdb.confignode.persistence.partition.PartitionInfo;
 import 
org.apache.iotdb.confignode.persistence.partition.maintainer.RegionCreateTask;
 import 
org.apache.iotdb.confignode.persistence.partition.maintainer.RegionDeleteTask;
-import 
org.apache.iotdb.confignode.persistence.partition.maintainer.RegionMaintainTask;
-import 
org.apache.iotdb.confignode.persistence.partition.maintainer.RegionMaintainType;
 import org.apache.iotdb.confignode.rpc.thrift.TDatabaseSchema;
 import org.apache.iotdb.confignode.rpc.thrift.TShowRegionReq;
 
@@ -154,31 +152,6 @@ public class PartitionInfoTest {
     Assert.assertEquals(partitionInfo, partitionInfo1);
   }
 
-  @Test
-  public void testLegacyRegionDeleteTasksAreFiltered() throws TException, 
IOException {
-    // Region deletion is owned by RemoveRegionGroupProcedure; the 
RegionMaintainer queue only
-    // recreates failed replicas. A legacy RegionDeleteTask (offered by an old 
version and replayed
-    // from a consensus log, or carried over in a snapshot) must be dropped 
rather than queued, so
-    // it cannot block the recreation of that region's other replicas.
-
-    // The offer plan mixes two RegionCreateTasks with one legacy 
RegionDeleteTask.
-    
partitionInfo.offerRegionMaintainTasks(generateOfferRegionMaintainTasksPlan());
-
-    // The DELETE task is filtered out at offer time; only the two CREATE 
tasks remain queued.
-    List<RegionMaintainTask> queuedTasks = 
partitionInfo.getRegionMaintainEntryList();
-    Assert.assertEquals(2, queuedTasks.size());
-    for (RegionMaintainTask task : queuedTasks) {
-      Assert.assertEquals(RegionMaintainType.CREATE, task.getType());
-    }
-
-    // A snapshot round-trip keeps the CREATE tasks and never resurrects a 
DELETE task.
-    Assert.assertTrue(partitionInfo.processTakeSnapshot(snapshotDir));
-    PartitionInfo loaded = new PartitionInfo();
-    loaded.processLoadSnapshot(snapshotDir);
-    Assert.assertEquals(partitionInfo, loaded);
-    Assert.assertEquals(2, loaded.getRegionMaintainEntryList().size());
-  }
-
   @Test
   public void testGetRegionType() {
 
diff --git 
a/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/procedure/impl/region/RemoveRegionGroupProcedureTest.java
 
b/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/procedure/impl/region/RemoveRegionGroupProcedureTest.java
deleted file mode 100644
index 3ca6efaf037..00000000000
--- 
a/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/procedure/impl/region/RemoveRegionGroupProcedureTest.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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.iotdb.confignode.procedure.impl.region;
-
-import org.apache.iotdb.common.rpc.thrift.TConsensusGroupId;
-import org.apache.iotdb.common.rpc.thrift.TConsensusGroupType;
-import org.apache.iotdb.common.rpc.thrift.TDataNodeLocation;
-import org.apache.iotdb.common.rpc.thrift.TEndPoint;
-import org.apache.iotdb.common.rpc.thrift.TRegionReplicaSet;
-import org.apache.iotdb.confignode.procedure.store.ProcedureFactory;
-
-import org.apache.tsfile.utils.PublicBAOS;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.io.DataOutputStream;
-import java.nio.ByteBuffer;
-import java.util.Arrays;
-
-public class RemoveRegionGroupProcedureTest {
-  @Test
-  public void serDeTest() throws Exception {
-    final TRegionReplicaSet regionReplicaSet =
-        new TRegionReplicaSet(
-            new TConsensusGroupId(TConsensusGroupType.DataRegion, 10),
-            Arrays.asList(
-                new TDataNodeLocation(
-                    1,
-                    new TEndPoint("127.0.0.1", 0),
-                    new TEndPoint("127.0.0.1", 1),
-                    new TEndPoint("127.0.0.1", 2),
-                    new TEndPoint("127.0.0.1", 3),
-                    new TEndPoint("127.0.0.1", 4)),
-                new TDataNodeLocation(
-                    2,
-                    new TEndPoint("127.0.0.1", 10),
-                    new TEndPoint("127.0.0.1", 11),
-                    new TEndPoint("127.0.0.1", 12),
-                    new TEndPoint("127.0.0.1", 13),
-                    new TEndPoint("127.0.0.1", 14))));
-    final RemoveRegionGroupProcedure procedure = new 
RemoveRegionGroupProcedure(regionReplicaSet);
-    // A non-zero cursor so the round-trip actually exercises 
currentReplicaIndex (de)serialization;
-    // equals/hashCode include it, so a dropped/garbled cursor would fail the 
assertion.
-    procedure.setCurrentReplicaIndex(1);
-    try (PublicBAOS byteArrayOutputStream = new PublicBAOS();
-        DataOutputStream outputStream = new 
DataOutputStream(byteArrayOutputStream)) {
-      procedure.serialize(outputStream);
-      ByteBuffer buffer =
-          ByteBuffer.wrap(byteArrayOutputStream.getBuf(), 0, 
byteArrayOutputStream.size());
-      // Exercises ProcedureType.REMOVE_REGION_GROUP_PROCEDURE + 
ProcedureFactory registration as
-      // well as the procedure's own serialize/deserialize.
-      Assert.assertEquals(procedure, 
ProcedureFactory.getInstance().create(buffer));
-    }
-  }
-}
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/RegionMigrateService.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/RegionMigrateService.java
index 69200271ee0..3b22d97880f 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/RegionMigrateService.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/RegionMigrateService.java
@@ -511,19 +511,17 @@ public class RegionMigrateService implements IService {
       // deletePeer: remove the peer from the consensus group
       TSStatus runResult = deletePeer();
       if (isFailed(runResult)) {
-        // A failed delete must NOT fall through to taskSucceed, otherwise the 
ConfigNode would
-        // forget the task while the peer/data is still present.
         taskFail(
             taskId,
             tRegionId,
             originalDataNode,
             TRegionMigrateFailedType.RemoveConsensusGroupFailed,
             runResult);
-        return;
       }
 
       // deleteRegion: delete region data
       runResult = deleteRegion();
+
       if (isFailed(runResult)) {
         taskFail(
             taskId,
@@ -531,7 +529,6 @@ public class RegionMigrateService implements IService {
             originalDataNode,
             TRegionMigrateFailedType.DeleteRegionFailed,
             runResult);
-        return;
       }
 
       taskSucceed(taskId, tRegionId, "DeletePeer");
@@ -551,13 +548,6 @@ public class RegionMigrateService implements IService {
         } else {
           SchemaRegionConsensusImpl.getInstance().deleteLocalPeer(regionId);
         }
-      } catch (ConsensusGroupNotExistException e) {
-        // The peer is already absent (e.g. a retry after a previous attempt 
removed it, or the
-        // region group is being deleted outright). Treat it as success and 
continue to delete data.
-        taskLogger.info(
-            "{}, The local peer of region {} does not exist, skip deleting it",
-            REGION_MIGRATE_PROCESS,
-            regionId);
       } catch (ConsensusException e) {
         String errorMsg =
             String.format(

Reply via email to