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

jiangmaolin pushed a commit to branch dev-5.5.1
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git

commit 3de91af7c91dca6331bb40a75d800de2d8a6dd88
Author: Haoran Meng <[email protected]>
AuthorDate: Thu Oct 24 10:03:36 2024 +0800

    Merge resource lock
---
 .../metadata/MetaDataInconsistentException.java    |  33 ++++++
 .../executor/engine/DriverExecuteExecutor.java     |  51 ++++++++++
 .../engine/DriverExecuteUpdateExecutor.java        |  56 +++++++++++
 .../src/main/antlr4/imports/SphereExKeyword.g4     | 108 ++++++++++++++++++++
 .../main/antlr4/imports/SphereExRALStatement.g4    | 112 +++++++++++++++++++++
 .../parser/autogen/KernelDistSQLStatement.g4       |  10 +-
 .../statement/ral/lock/ShowDistLocksStatement.java |  26 +++++
 .../ral/lock/UnlockDistLockStatement.java          |  32 ++++++
 .../ShowLastExecuteFailedNodesStatement.java       |  26 +++++
 .../DropLastExecuteFailedNodeStatement.java        |  34 +++++++
 .../distsql/ral/lock/ShowDistLocksExecutor.java    |  70 +++++++++++++
 .../ral/lock/UnlockDistLockStatementExecutor.java  |  53 ++++++++++
 .../ShowLastExecuteFailedNodesExecutor.java        |  61 +++++++++++
 .../DropLastExecuteFailedNodeExecutor.java         |  44 ++++++++
 .../proxy/backend/connector/DatabaseConnector.java |   6 ++
 .../DatabaseOperateBackendHandlerFactory.java      |   6 ++
 .../database/DropDatabaseBackendHandler.java       |  16 +++
 .../distsql/DistSQLBackendHandlerFactory.java      |  42 ++++++++
 ...stsql.handler.engine.query.DistSQLQueryExecutor |   3 +
 ...sql.handler.engine.update.DistSQLUpdateExecutor |   3 +
 .../handler/ProxyBackendHandlerFactoryTest.java    |   3 +
 .../DatabaseOperateBackendHandlerFactoryTest.java  |   3 +
 proxy/backend/{ => enterprise}/pom.xml             |  17 ++--
 .../EnterpriseAdvancedProxySQLExecutor.java        | 101 +++++++++++++++++++
 .../LockRequiredRefreshTableMetaDataExecutor.java  |  73 ++++++++++++++
 ...ler.engine.update.AdvancedDistSQLUpdateExecutor |  18 ++++
 ...roxy.backend.connector.AdvancedProxySQLExecutor |  18 ++++
 proxy/backend/pom.xml                              |   3 +
 28 files changed, 1020 insertions(+), 8 deletions(-)

diff --git 
a/infra/common/src/main/java/com/sphereex/dbplusengine/infra/exception/metadata/MetaDataInconsistentException.java
 
b/infra/common/src/main/java/com/sphereex/dbplusengine/infra/exception/metadata/MetaDataInconsistentException.java
new file mode 100644
index 00000000000..af0664375dd
--- /dev/null
+++ 
b/infra/common/src/main/java/com/sphereex/dbplusengine/infra/exception/metadata/MetaDataInconsistentException.java
@@ -0,0 +1,33 @@
+/*
+ * 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 com.sphereex.dbplusengine.infra.exception.metadata;
+
+import 
org.apache.shardingsphere.infra.exception.core.external.sql.sqlstate.XOpenSQLState;
+import 
org.apache.shardingsphere.infra.exception.core.external.sql.type.kernel.category.MetaDataSQLException;
+
+/**
+ * Meta data inconsistent exception.
+ */
+public final class MetaDataInconsistentException extends MetaDataSQLException {
+    
+    private static final long serialVersionUID = 2407142821533632803L;
+    
+    public MetaDataInconsistentException() {
+        super(XOpenSQLState.GENERAL_ERROR, 61, "The metadata is inconsistent 
because the last SQL execute failed, please execute `SHOW LAST EXECUTE FAILED 
NODES` for detail.");
+    }
+}
diff --git 
a/jdbc/src/main/java/org/apache/shardingsphere/driver/executor/engine/DriverExecuteExecutor.java
 
b/jdbc/src/main/java/org/apache/shardingsphere/driver/executor/engine/DriverExecuteExecutor.java
index 699b512d2db..930f99c23ac 100644
--- 
a/jdbc/src/main/java/org/apache/shardingsphere/driver/executor/engine/DriverExecuteExecutor.java
+++ 
b/jdbc/src/main/java/org/apache/shardingsphere/driver/executor/engine/DriverExecuteExecutor.java
@@ -17,6 +17,11 @@
 
 package org.apache.shardingsphere.driver.executor.engine;
 
+import com.sphereex.dbplusengine.SphereEx;
+import com.sphereex.dbplusengine.infra.exception.lock.LockWaitTimeoutException;
+import com.sphereex.dbplusengine.mode.lock.ResourceLockDefinitionManager;
+import com.sphereex.dbplusengine.mode.lock.checker.SphereExLockChecker;
+import 
com.sphereex.dbplusengine.mode.lock.manager.definition.ResourceLockDefinition;
 import lombok.RequiredArgsConstructor;
 import 
org.apache.shardingsphere.driver.executor.callback.add.StatementAddCallback;
 import 
org.apache.shardingsphere.driver.executor.callback.execute.ExecuteQueryCallbackFactory;
@@ -26,16 +31,21 @@ import 
org.apache.shardingsphere.driver.executor.engine.pushdown.jdbc.DriverJDBC
 import 
org.apache.shardingsphere.driver.executor.engine.pushdown.raw.DriverRawPushDownExecuteExecutor;
 import 
org.apache.shardingsphere.driver.jdbc.core.connection.ShardingSphereConnection;
 import 
org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
+import org.apache.shardingsphere.infra.binder.context.type.TableAvailable;
+import 
org.apache.shardingsphere.infra.config.props.temporary.TemporaryConfigurationPropertyKey;
 import org.apache.shardingsphere.infra.connection.kernel.KernelProcessor;
+import org.apache.shardingsphere.infra.database.core.type.DatabaseTypeRegistry;
 import org.apache.shardingsphere.infra.executor.sql.context.ExecutionContext;
 import 
org.apache.shardingsphere.infra.executor.sql.execute.engine.driver.jdbc.JDBCExecutionUnit;
 import 
org.apache.shardingsphere.infra.executor.sql.execute.engine.driver.jdbc.JDBCExecutor;
 import 
org.apache.shardingsphere.infra.executor.sql.execute.engine.raw.RawExecutor;
 import 
org.apache.shardingsphere.infra.executor.sql.prepare.driver.DriverExecutionPrepareEngine;
+import org.apache.shardingsphere.infra.lock.GlobalLockNames;
 import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
 import 
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
 import 
org.apache.shardingsphere.infra.rule.attribute.raw.RawExecutionRuleAttribute;
 import org.apache.shardingsphere.infra.session.query.QueryContext;
+import org.apache.shardingsphere.mode.lock.GlobalLockDefinition;
 import org.apache.shardingsphere.mode.metadata.refresher.MetaDataRefreshEngine;
 import org.apache.shardingsphere.sqlfederation.engine.SQLFederationEngine;
 import 
org.apache.shardingsphere.sqlfederation.executor.context.SQLFederationContext;
@@ -44,6 +54,8 @@ import java.sql.Connection;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
+import java.util.Collection;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Optional;
 
@@ -102,12 +114,51 @@ public final class DriverExecuteExecutor {
         }
         ExecutionContext executionContext =
                 new KernelProcessor().generateExecutionContext(queryContext, 
metaData.getGlobalRuleMetaData(), metaData.getProps(), 
connection.getDatabaseConnectionManager().getConnectionContext());
+        // SPEX ADDED: BEGIN
+        new 
SphereExLockChecker(connection.getContextManager().getComputeNodeInstanceContext().getLockContext(),
+                
connection.getContextManager().getMetaDataContexts().getMetaData().getTemporaryProps())
+                .checkUnlock(connection.getCurrentDatabaseName(), 
executionContext.getSqlStatementContext());
+        Optional<ResourceLockDefinitionManager> lockManager = 
getLockManager(executionContext);
+        if (lockManager.isPresent()) {
+            GlobalLockDefinition globalLockDefinition = new 
GlobalLockDefinition(GlobalLockNames.UPDATE_METADATA.getLockName());
+            long timeout = 
connection.getContextManager().getMetaDataContexts().getMetaData().getTemporaryProps().<Long>getValue(TemporaryConfigurationPropertyKey.LOCK_TIME_OUT_MILLISECONDS);
+            if 
(!connection.getContextManager().getComputeNodeInstanceContext().getLockContext().tryLock(globalLockDefinition,
 timeout)) {
+                throw new 
LockWaitTimeoutException(GlobalLockNames.UPDATE_METADATA, timeout);
+            }
+            ResourceLockDefinition resourceLockDefinition = null;
+            try {
+                resourceLockDefinition = tryLock(lockManager.get(), 
executionContext);
+                return executePushDown(database, executionContext, 
prepareEngine, executeCallback, addCallback, replayCallback);
+            } finally {
+                
connection.getContextManager().getComputeNodeInstanceContext().getLockContext().unlock(globalLockDefinition);
+                lockManager.get().unlock(resourceLockDefinition);
+            }
+        }
+        // SPEX ADDED: END
         return executePushDown(database, executionContext, prepareEngine, 
executeCallback, addCallback, replayCallback);
     }
     
     private MetaDataRefreshEngine getMetaDataRefreshEngine(final 
ShardingSphereDatabase database) {
         return new 
MetaDataRefreshEngine(connection.getContextManager().getPersistServiceFacade().getMetaDataManagerPersistService(),
 database, metaData.getProps());
     }
+
+    @SphereEx
+    private Optional<ResourceLockDefinitionManager> getLockManager(final 
ExecutionContext executionContext) {
+        return 
MetaDataRefreshEngine.isRefreshMetaDataRequired(executionContext.getSqlStatementContext())
 ? connection.getContextManager().getResourceLockDefinitionManager() : 
Optional.empty();
+    }
+
+    @SphereEx
+    private ResourceLockDefinition tryLock(final ResourceLockDefinitionManager 
lockManager, final ExecutionContext executionContext) {
+        SQLStatementContext sqlStatementContext = 
executionContext.getSqlStatementContext();
+        if (sqlStatementContext instanceof TableAvailable) {
+            String schemaName = ((TableAvailable) 
sqlStatementContext).getTablesContext().getSchemaName()
+                    .orElseGet(() -> new 
DatabaseTypeRegistry(sqlStatementContext.getDatabaseType()).getDefaultSchemaName(connection.getCurrentDatabaseName()));
+            Collection<String> tableNames = new HashSet<>(((TableAvailable) 
sqlStatementContext).getTablesContext().getTableNames());
+            return lockManager.tryLock(connection.getCurrentDatabaseName(), 
schemaName, tableNames);
+        }
+        String schemaName = new 
DatabaseTypeRegistry(sqlStatementContext.getDatabaseType()).getDefaultSchemaName(connection.getCurrentDatabaseName());
+        return lockManager.tryLock(connection.getCurrentDatabaseName(), 
schemaName);
+    }
     
     @SuppressWarnings("rawtypes")
     private boolean executePushDown(final ShardingSphereDatabase database, 
final ExecutionContext executionContext, final 
DriverExecutionPrepareEngine<JDBCExecutionUnit, Connection> prepareEngine,
diff --git 
a/jdbc/src/main/java/org/apache/shardingsphere/driver/executor/engine/DriverExecuteUpdateExecutor.java
 
b/jdbc/src/main/java/org/apache/shardingsphere/driver/executor/engine/DriverExecuteUpdateExecutor.java
index 806fe12bc63..70a823c01ea 100644
--- 
a/jdbc/src/main/java/org/apache/shardingsphere/driver/executor/engine/DriverExecuteUpdateExecutor.java
+++ 
b/jdbc/src/main/java/org/apache/shardingsphere/driver/executor/engine/DriverExecuteUpdateExecutor.java
@@ -17,6 +17,11 @@
 
 package org.apache.shardingsphere.driver.executor.engine;
 
+import com.sphereex.dbplusengine.SphereEx;
+import com.sphereex.dbplusengine.infra.exception.lock.LockWaitTimeoutException;
+import com.sphereex.dbplusengine.mode.lock.ResourceLockDefinitionManager;
+import com.sphereex.dbplusengine.mode.lock.checker.SphereExLockChecker;
+import 
com.sphereex.dbplusengine.mode.lock.manager.definition.ResourceLockDefinition;
 import lombok.RequiredArgsConstructor;
 import 
org.apache.shardingsphere.driver.executor.callback.add.StatementAddCallback;
 import 
org.apache.shardingsphere.driver.executor.callback.execute.StatementExecuteUpdateCallback;
@@ -24,19 +29,29 @@ import 
org.apache.shardingsphere.driver.executor.callback.replay.StatementReplay
 import 
org.apache.shardingsphere.driver.executor.engine.pushdown.jdbc.DriverJDBCPushDownExecuteUpdateExecutor;
 import 
org.apache.shardingsphere.driver.executor.engine.pushdown.raw.DriverRawPushDownExecuteUpdateExecutor;
 import 
org.apache.shardingsphere.driver.jdbc.core.connection.ShardingSphereConnection;
+import 
org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
+import org.apache.shardingsphere.infra.binder.context.type.TableAvailable;
+import 
org.apache.shardingsphere.infra.config.props.temporary.TemporaryConfigurationPropertyKey;
 import org.apache.shardingsphere.infra.connection.kernel.KernelProcessor;
+import org.apache.shardingsphere.infra.database.core.type.DatabaseTypeRegistry;
 import org.apache.shardingsphere.infra.executor.sql.context.ExecutionContext;
 import 
org.apache.shardingsphere.infra.executor.sql.execute.engine.driver.jdbc.JDBCExecutionUnit;
 import 
org.apache.shardingsphere.infra.executor.sql.execute.engine.driver.jdbc.JDBCExecutor;
 import 
org.apache.shardingsphere.infra.executor.sql.execute.engine.raw.RawExecutor;
 import 
org.apache.shardingsphere.infra.executor.sql.prepare.driver.DriverExecutionPrepareEngine;
+import org.apache.shardingsphere.infra.lock.GlobalLockNames;
 import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
 import 
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
 import 
org.apache.shardingsphere.infra.rule.attribute.raw.RawExecutionRuleAttribute;
 import org.apache.shardingsphere.infra.session.query.QueryContext;
+import org.apache.shardingsphere.mode.lock.GlobalLockDefinition;
+import org.apache.shardingsphere.mode.metadata.refresher.MetaDataRefreshEngine;
 
 import java.sql.Connection;
 import java.sql.SQLException;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Optional;
 
 /**
  * Driver execute update executor.
@@ -76,8 +91,49 @@ public final class DriverExecuteUpdateExecutor {
                              final StatementExecuteUpdateCallback 
updateCallback, final StatementAddCallback addCallback, final 
StatementReplayCallback replayCallback) throws SQLException {
         ExecutionContext executionContext =
                 new KernelProcessor().generateExecutionContext(queryContext, 
metaData.getGlobalRuleMetaData(), metaData.getProps(), 
connection.getDatabaseConnectionManager().getConnectionContext());
+        // SPEX ADDED: BEGIN
+        new 
SphereExLockChecker(connection.getContextManager().getComputeNodeInstanceContext().getLockContext(),
+                
connection.getContextManager().getMetaDataContexts().getMetaData().getTemporaryProps())
+                .checkUnlock(connection.getCurrentDatabaseName(), 
executionContext.getSqlStatementContext());
+        Optional<ResourceLockDefinitionManager> lockManager = 
getLockManager(executionContext);
+        if (lockManager.isPresent()) {
+            GlobalLockDefinition globalLockDefinition = new 
GlobalLockDefinition(GlobalLockNames.UPDATE_METADATA.getLockName());
+            long timeout = 
connection.getContextManager().getMetaDataContexts().getMetaData().getTemporaryProps().<Long>getValue(TemporaryConfigurationPropertyKey.LOCK_TIME_OUT_MILLISECONDS);
+            if 
(!connection.getContextManager().getComputeNodeInstanceContext().getLockContext().tryLock(globalLockDefinition,
 timeout)) {
+                throw new 
LockWaitTimeoutException(GlobalLockNames.UPDATE_METADATA, timeout);
+            }
+            ResourceLockDefinition resourceLockDefinition = null;
+            try {
+                resourceLockDefinition = tryLock(lockManager.get(), 
executionContext);
+                return 
database.getRuleMetaData().getAttributes(RawExecutionRuleAttribute.class).isEmpty()
+                        ? jdbcPushDownExecutor.executeUpdate(database, 
executionContext, prepareEngine, updateCallback, addCallback, replayCallback)
+                        : rawPushDownExecutor.executeUpdate(database, 
executionContext);
+            } finally {
+                
connection.getContextManager().getComputeNodeInstanceContext().getLockContext().unlock(globalLockDefinition);
+                lockManager.get().unlock(resourceLockDefinition);
+            }
+        }
+        // SPEX ADDED: END
         return 
database.getRuleMetaData().getAttributes(RawExecutionRuleAttribute.class).isEmpty()
                 ? jdbcPushDownExecutor.executeUpdate(database, 
executionContext, prepareEngine, updateCallback, addCallback, replayCallback)
                 : rawPushDownExecutor.executeUpdate(database, 
executionContext);
     }
+
+    @SphereEx
+    private Optional<ResourceLockDefinitionManager> getLockManager(final 
ExecutionContext executionContext) {
+        return 
MetaDataRefreshEngine.isRefreshMetaDataRequired(executionContext.getSqlStatementContext())
 ? connection.getContextManager().getResourceLockDefinitionManager() : 
Optional.empty();
+    }
+
+    @SphereEx
+    private ResourceLockDefinition tryLock(final ResourceLockDefinitionManager 
lockManager, final ExecutionContext executionContext) {
+        SQLStatementContext sqlStatementContext = 
executionContext.getSqlStatementContext();
+        if (sqlStatementContext instanceof TableAvailable) {
+            String schemaName = ((TableAvailable) 
sqlStatementContext).getTablesContext().getSchemaName()
+                    .orElseGet(() -> new 
DatabaseTypeRegistry(sqlStatementContext.getDatabaseType()).getDefaultSchemaName(connection.getCurrentDatabaseName()));
+            Collection<String> tableNames = new HashSet<>(((TableAvailable) 
sqlStatementContext).getTablesContext().getTableNames());
+            return lockManager.tryLock(connection.getCurrentDatabaseName(), 
schemaName, tableNames);
+        }
+        String schemaName = new 
DatabaseTypeRegistry(sqlStatementContext.getDatabaseType()).getDefaultSchemaName(connection.getCurrentDatabaseName());
+        return lockManager.tryLock(connection.getCurrentDatabaseName(), 
schemaName);
+    }
 }
diff --git a/parser/distsql/engine/src/main/antlr4/imports/SphereExKeyword.g4 
b/parser/distsql/engine/src/main/antlr4/imports/SphereExKeyword.g4
new file mode 100644
index 00000000000..5774c55c5f8
--- /dev/null
+++ b/parser/distsql/engine/src/main/antlr4/imports/SphereExKeyword.g4
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ */
+
+lexer grammar SphereExKeyword;
+
+import Alphabet;
+
+LICENSE
+    : L I C E N S E
+    ;
+
+INFO
+    : I N F O
+    ;
+
+REGISTER
+    : R E G I S T E R
+    ;
+
+SERIES
+    : S E R I E S
+    ;
+
+NUMBER
+    : N U M B E R
+    ;
+
+STRUCTURE
+    : S T R U C T U R E
+    ;
+
+WARMUP
+    : W A R M U P
+    ;
+
+LOADING
+    : L O A D I N G
+    ;
+
+STATUS
+    : S T A T U S
+    ;
+
+CONVERTING
+    : C O N V E R T I N G
+    ;
+
+LOCKS
+    : L O C K S
+    ;
+
+DIRECTORY
+    : D I R E C T O R Y
+    ;
+
+LAST
+    : L A S T
+    ;
+
+EXECUTE
+    : E X E C U T E
+    ;
+
+FAILED
+    : F A I L E D
+    ;
+
+MANAGER
+    : M A N A G E R
+    ;
+
+REFERENCES
+    : R E F E R E N C E S
+    ;
+
+REFERENCE
+    : R E F E R E N C E
+    ;
+
+DDL
+    : D D L
+    ;
+
+COLUMNS
+    : C O L U M N S
+    ;
+
+DATA_TYPE
+    : D A T A UL_ T Y P E
+    ;
+
+INSTANCE
+    : I N S T A N C E
+    ;
diff --git 
a/parser/distsql/engine/src/main/antlr4/imports/SphereExRALStatement.g4 
b/parser/distsql/engine/src/main/antlr4/imports/SphereExRALStatement.g4
new file mode 100644
index 00000000000..a739f803588
--- /dev/null
+++ b/parser/distsql/engine/src/main/antlr4/imports/SphereExRALStatement.g4
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+
+grammar SphereExRALStatement;
+
+import SphereExKeyword, BaseRule;
+
+showInstanceStorageUnits
+    : SHOW INSTANCE STORAGE UNITS
+    ;
+
+showLicenseInfo
+    : SHOW LICENSE INFO (license)? 
+    ;
+
+showLicenseStatus
+    : SHOW LICENSE STATUS
+    ;
+
+registerLicense
+    : REGISTER LICENSE license
+    ;
+
+license
+    : STRING_
+    ;
+
+showSeriesNumber
+    : SHOW SERIES NUMBER
+    ;
+
+showLoadingMetadataList
+    : SHOW LOADING METADATA LIST (FROM databaseName)?
+    ;
+
+showLoadingMetadataStatus
+    : SHOW LOADING METADATA STATUS storageUnitName (FROM databaseName)?
+    ;
+
+showConvertingList
+    : SHOW CONVERTING LIST (FROM databaseName)?
+    ;
+
+showConvertingStatus
+    : SHOW CONVERTING STATUS tableName (FROM databaseName)?
+    ;
+
+exportDatabaseStructure
+    : EXPORT DATABASE STRUCTURE (FROM databaseName)? TO FILE filePath
+    ;
+
+showDistLocks
+    : SHOW DIST LOCKS
+    ;
+
+unlockDistLock
+    : UNLOCK DIST LOCK lockKey
+    ;
+
+showLastExecuteFailedNodes
+    : SHOW LAST EXECUTE FAILED NODES
+    ;
+
+dropLastExecuteFailedNode
+    : DROP LAST EXECUTE FAILED NODE instanceId (COMMA_ instanceId)*
+    ;
+
+showKeyManagerReference
+    : SHOW KEY MANAGER (REFERENCES | REFERENCE referenceKey)
+    ;
+
+dropKeyManagerReference
+    : DROP KEY MANAGER REFERENCE referenceKey (COMMA_ referenceKey)*
+    ;
+
+referenceKey
+    : STRING_
+    ;
+
+lockKey
+    : STRING_
+    ;
+
+filePath
+    : STRING_
+    ;
+
+warmupSQL
+    : WARMUP sql
+    ;
+
+sql
+    : STRING_
+    ;
+
+instanceId
+    : IDENTIFIER_ | STRING_
+    ;
diff --git 
a/parser/distsql/engine/src/main/antlr4/org/apache/shardingsphere/distsql/parser/autogen/KernelDistSQLStatement.g4
 
b/parser/distsql/engine/src/main/antlr4/org/apache/shardingsphere/distsql/parser/autogen/KernelDistSQLStatement.g4
index ea54423a6ad..8278568b115 100644
--- 
a/parser/distsql/engine/src/main/antlr4/org/apache/shardingsphere/distsql/parser/autogen/KernelDistSQLStatement.g4
+++ 
b/parser/distsql/engine/src/main/antlr4/org/apache/shardingsphere/distsql/parser/autogen/KernelDistSQLStatement.g4
@@ -17,7 +17,9 @@
 
 grammar KernelDistSQLStatement;
 
-import Symbol, RALStatement, RDLStatement, RQLStatement;
+// SPEX CHANGED: BEGIN
+import Symbol, RALStatement, RDLStatement, RQLStatement, SphereExRALStatement;
+// SPEX CHANGED: END
 
 execute
     : (registerStorageUnit
@@ -51,5 +53,11 @@ execute
     | showPluginImplementations
     | showKeyGenerateAlgorithmPlugins
     | showLoadBalanceAlgorithmPlugins
+    // SPEX ADDED: BEGIN
+    | showDistLocks
+    | unlockDistLock
+    | showLastExecuteFailedNodes
+    | dropLastExecuteFailedNode
+    // SPEX ADDED: END
     ) SEMI_? EOF
     ;
diff --git 
a/parser/distsql/statement/src/main/java/com/sphereex/dbplusengine/distsql/statement/ral/lock/ShowDistLocksStatement.java
 
b/parser/distsql/statement/src/main/java/com/sphereex/dbplusengine/distsql/statement/ral/lock/ShowDistLocksStatement.java
new file mode 100644
index 00000000000..6f91d666978
--- /dev/null
+++ 
b/parser/distsql/statement/src/main/java/com/sphereex/dbplusengine/distsql/statement/ral/lock/ShowDistLocksStatement.java
@@ -0,0 +1,26 @@
+/*
+ * 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 com.sphereex.dbplusengine.distsql.statement.ral.lock;
+
+import 
org.apache.shardingsphere.distsql.statement.ral.queryable.QueryableRALStatement;
+
+/**
+ * Show dist locks statement.
+ */
+public final class ShowDistLocksStatement extends QueryableRALStatement {
+}
diff --git 
a/parser/distsql/statement/src/main/java/com/sphereex/dbplusengine/distsql/statement/ral/lock/UnlockDistLockStatement.java
 
b/parser/distsql/statement/src/main/java/com/sphereex/dbplusengine/distsql/statement/ral/lock/UnlockDistLockStatement.java
new file mode 100644
index 00000000000..a93c7a479f5
--- /dev/null
+++ 
b/parser/distsql/statement/src/main/java/com/sphereex/dbplusengine/distsql/statement/ral/lock/UnlockDistLockStatement.java
@@ -0,0 +1,32 @@
+/*
+ * 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 com.sphereex.dbplusengine.distsql.statement.ral.lock;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import 
org.apache.shardingsphere.distsql.statement.ral.updatable.UpdatableRALStatement;
+
+/**
+ * Unlock dist lock statement.
+ */
+@RequiredArgsConstructor
+@Getter
+public final class UnlockDistLockStatement extends UpdatableRALStatement {
+    
+    private final String lockKey;
+}
diff --git 
a/parser/distsql/statement/src/main/java/com/sphereex/dbplusengine/distsql/statement/ral/queryable/ShowLastExecuteFailedNodesStatement.java
 
b/parser/distsql/statement/src/main/java/com/sphereex/dbplusengine/distsql/statement/ral/queryable/ShowLastExecuteFailedNodesStatement.java
new file mode 100644
index 00000000000..46a5ade5d21
--- /dev/null
+++ 
b/parser/distsql/statement/src/main/java/com/sphereex/dbplusengine/distsql/statement/ral/queryable/ShowLastExecuteFailedNodesStatement.java
@@ -0,0 +1,26 @@
+/*
+ * 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 com.sphereex.dbplusengine.distsql.statement.ral.queryable;
+
+import 
org.apache.shardingsphere.distsql.statement.ral.queryable.QueryableRALStatement;
+
+/**
+ * Show last execute failed nodes statement.
+ */
+public final class ShowLastExecuteFailedNodesStatement extends 
QueryableRALStatement {
+}
diff --git 
a/parser/distsql/statement/src/main/java/com/sphereex/dbplusengine/distsql/statement/ral/updatable/DropLastExecuteFailedNodeStatement.java
 
b/parser/distsql/statement/src/main/java/com/sphereex/dbplusengine/distsql/statement/ral/updatable/DropLastExecuteFailedNodeStatement.java
new file mode 100644
index 00000000000..6ed1c024cab
--- /dev/null
+++ 
b/parser/distsql/statement/src/main/java/com/sphereex/dbplusengine/distsql/statement/ral/updatable/DropLastExecuteFailedNodeStatement.java
@@ -0,0 +1,34 @@
+/*
+ * 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 com.sphereex.dbplusengine.distsql.statement.ral.updatable;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import 
org.apache.shardingsphere.distsql.statement.ral.updatable.UpdatableRALStatement;
+
+import java.util.Collection;
+
+/**
+ * Drop last execute failed node statement.
+ */
+@RequiredArgsConstructor
+@Getter
+public final class DropLastExecuteFailedNodeStatement extends 
UpdatableRALStatement {
+    
+    private final Collection<String> droppedInstanceIds;
+}
diff --git 
a/proxy/backend/core/src/main/java/com/sphereex/dbplusengine/proxy/backend/handler/distsql/ral/lock/ShowDistLocksExecutor.java
 
b/proxy/backend/core/src/main/java/com/sphereex/dbplusengine/proxy/backend/handler/distsql/ral/lock/ShowDistLocksExecutor.java
new file mode 100644
index 00000000000..5f35178de27
--- /dev/null
+++ 
b/proxy/backend/core/src/main/java/com/sphereex/dbplusengine/proxy/backend/handler/distsql/ral/lock/ShowDistLocksExecutor.java
@@ -0,0 +1,70 @@
+/*
+ * 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 com.sphereex.dbplusengine.proxy.backend.handler.distsql.ral.lock;
+
+import 
com.sphereex.dbplusengine.distsql.statement.ral.lock.ShowDistLocksStatement;
+import com.sphereex.dbplusengine.mode.lock.SphereExLockContext;
+import com.sphereex.dbplusengine.mode.lock.manager.definition.SphereExLockName;
+import 
com.sphereex.dbplusengine.mode.lock.manager.definition.impl.SphereExSchemaLockName;
+import 
com.sphereex.dbplusengine.mode.lock.manager.definition.impl.SphereExTableLockName;
+import lombok.Setter;
+import 
org.apache.shardingsphere.distsql.handler.engine.query.DistSQLQueryExecutor;
+import 
org.apache.shardingsphere.distsql.handler.required.DistSQLExecutorClusterModeRequired;
+import 
org.apache.shardingsphere.infra.merge.result.impl.local.LocalDataQueryResultRow;
+import org.apache.shardingsphere.mode.manager.ContextManager;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.stream.Collectors;
+
+/**
+ * Show dist locks executor.
+ */
+@DistSQLExecutorClusterModeRequired
+@Setter
+public final class ShowDistLocksExecutor implements 
DistSQLQueryExecutor<ShowDistLocksStatement> {
+    
+    @Override
+    public Collection<String> getColumnNames(final ShowDistLocksStatement 
sqlStatement) {
+        return Arrays.asList("lock_level", "lock_name", "lock_key");
+    }
+    
+    @Override
+    public Collection<LocalDataQueryResultRow> getRows(final 
ShowDistLocksStatement sqlStatement, final ContextManager contextManager) {
+        Map<String, SphereExLockName> lockMap = ((SphereExLockContext) 
contextManager.getComputeNodeInstanceContext().getLockContext()).getResourceLockManager().getLockNames();
+        return 
lockMap.entrySet().stream().map(this::buildRow).collect(Collectors.toList());
+    }
+    
+    private LocalDataQueryResultRow buildRow(final Entry<String, 
SphereExLockName> entry) {
+        String lockLevel = "database";
+        String lockName = entry.getValue().getLockName();
+        if (entry.getValue() instanceof SphereExSchemaLockName) {
+            lockLevel = "schema";
+        } else if (entry.getValue() instanceof SphereExTableLockName) {
+            lockLevel = "table";
+        }
+        return new LocalDataQueryResultRow(lockLevel, lockName, 
entry.getKey());
+    }
+    
+    @Override
+    public Class<ShowDistLocksStatement> getType() {
+        return ShowDistLocksStatement.class;
+    }
+}
diff --git 
a/proxy/backend/core/src/main/java/com/sphereex/dbplusengine/proxy/backend/handler/distsql/ral/lock/UnlockDistLockStatementExecutor.java
 
b/proxy/backend/core/src/main/java/com/sphereex/dbplusengine/proxy/backend/handler/distsql/ral/lock/UnlockDistLockStatementExecutor.java
new file mode 100644
index 00000000000..006942e4192
--- /dev/null
+++ 
b/proxy/backend/core/src/main/java/com/sphereex/dbplusengine/proxy/backend/handler/distsql/ral/lock/UnlockDistLockStatementExecutor.java
@@ -0,0 +1,53 @@
+/*
+ * 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 com.sphereex.dbplusengine.proxy.backend.handler.distsql.ral.lock;
+
+import 
com.sphereex.dbplusengine.distsql.statement.ral.lock.UnlockDistLockStatement;
+import com.sphereex.dbplusengine.infra.exception.lock.LockNotFoundException;
+import com.sphereex.dbplusengine.mode.lock.SphereExLockContext;
+import com.sphereex.dbplusengine.mode.lock.manager.definition.SphereExLockName;
+import 
org.apache.shardingsphere.distsql.handler.engine.update.DistSQLUpdateExecutor;
+import 
org.apache.shardingsphere.distsql.handler.required.DistSQLExecutorClusterModeRequired;
+import 
org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions;
+import org.apache.shardingsphere.mode.manager.ContextManager;
+
+import java.sql.SQLException;
+import java.util.Map;
+
+/**
+ * Unlock dist lock statement executor.
+ */
+@DistSQLExecutorClusterModeRequired
+public final class UnlockDistLockStatementExecutor implements 
DistSQLUpdateExecutor<UnlockDistLockStatement> {
+    
+    @Override
+    public void executeUpdate(final UnlockDistLockStatement sqlStatement, 
final ContextManager contextManager) throws SQLException {
+        Map<String, SphereExLockName> lockMap = ((SphereExLockContext) 
contextManager.getComputeNodeInstanceContext().getLockContext()).getResourceLockManager().getLockNames();
+        ShardingSpherePreconditions.checkContainsKey(lockMap, 
sqlStatement.getLockKey(), () -> new 
LockNotFoundException(sqlStatement.getLockKey()));
+        // TODO refresh meta data contexts before release lock
+        String instanceId = 
contextManager.getComputeNodeInstanceContext().getInstance().getMetaData().getId();
+        
contextManager.getPersistServiceFacade().getConsistencyPersistService().removeConsistencyAckRecord(instanceId);
+        SphereExLockName lockName = lockMap.get(sqlStatement.getLockKey());
+        ((SphereExLockContext) 
contextManager.getComputeNodeInstanceContext().getLockContext()).getResourceLockManager().handleLockReleased(lockName);
+    }
+    
+    @Override
+    public Class<UnlockDistLockStatement> getType() {
+        return UnlockDistLockStatement.class;
+    }
+}
diff --git 
a/proxy/backend/core/src/main/java/com/sphereex/dbplusengine/proxy/backend/handler/distsql/ral/queryable/ShowLastExecuteFailedNodesExecutor.java
 
b/proxy/backend/core/src/main/java/com/sphereex/dbplusengine/proxy/backend/handler/distsql/ral/queryable/ShowLastExecuteFailedNodesExecutor.java
new file mode 100644
index 00000000000..c124222c0e6
--- /dev/null
+++ 
b/proxy/backend/core/src/main/java/com/sphereex/dbplusengine/proxy/backend/handler/distsql/ral/queryable/ShowLastExecuteFailedNodesExecutor.java
@@ -0,0 +1,61 @@
+/*
+ * 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 com.sphereex.dbplusengine.proxy.backend.handler.distsql.ral.queryable;
+
+import 
com.sphereex.dbplusengine.distsql.statement.ral.queryable.ShowLastExecuteFailedNodesStatement;
+import lombok.Setter;
+import 
org.apache.shardingsphere.distsql.handler.engine.query.DistSQLQueryExecutor;
+import 
org.apache.shardingsphere.distsql.handler.required.DistSQLExecutorClusterModeRequired;
+import org.apache.shardingsphere.infra.instance.ComputeNodeInstance;
+import 
org.apache.shardingsphere.infra.instance.metadata.proxy.ProxyInstanceMetaData;
+import 
org.apache.shardingsphere.infra.merge.result.impl.local.LocalDataQueryResultRow;
+import org.apache.shardingsphere.mode.manager.ContextManager;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.stream.Collectors;
+
+/**
+ * Show last execute failed nodes executor.
+ */
+@DistSQLExecutorClusterModeRequired
+@Setter
+public final class ShowLastExecuteFailedNodesExecutor implements 
DistSQLQueryExecutor<ShowLastExecuteFailedNodesStatement> {
+    
+    @Override
+    public Collection<String> getColumnNames(final 
ShowLastExecuteFailedNodesStatement sqlStatement) {
+        return Arrays.asList("instance_id", "instance_type", "host", "port");
+    }
+    
+    @Override
+    public Collection<LocalDataQueryResultRow> getRows(final 
ShowLastExecuteFailedNodesStatement sqlStatement, final ContextManager 
contextManager) {
+        Collection<String> failedNodes = 
contextManager.getPersistServiceFacade().getConsistencyPersistService().loadAllUnAckedConsistencyNodes();
+        return 
contextManager.getComputeNodeInstanceContext().getAllClusterInstances().stream().filter(each
 -> failedNodes.contains(each.getMetaData().getId()))
+                .map(this::buildRow).collect(Collectors.toList());
+    }
+    
+    private LocalDataQueryResultRow buildRow(final ComputeNodeInstance 
computeNodeInstance) {
+        return new 
LocalDataQueryResultRow(computeNodeInstance.getMetaData().getId(), 
computeNodeInstance.getMetaData().getType(), 
computeNodeInstance.getMetaData().getIp(),
+                computeNodeInstance.getMetaData() instanceof 
ProxyInstanceMetaData ? ((ProxyInstanceMetaData) 
computeNodeInstance.getMetaData()).getPort() : -1);
+    }
+    
+    @Override
+    public Class<ShowLastExecuteFailedNodesStatement> getType() {
+        return ShowLastExecuteFailedNodesStatement.class;
+    }
+}
diff --git 
a/proxy/backend/core/src/main/java/com/sphereex/dbplusengine/proxy/backend/handler/distsql/ral/updatable/DropLastExecuteFailedNodeExecutor.java
 
b/proxy/backend/core/src/main/java/com/sphereex/dbplusengine/proxy/backend/handler/distsql/ral/updatable/DropLastExecuteFailedNodeExecutor.java
new file mode 100644
index 00000000000..3ed5b863122
--- /dev/null
+++ 
b/proxy/backend/core/src/main/java/com/sphereex/dbplusengine/proxy/backend/handler/distsql/ral/updatable/DropLastExecuteFailedNodeExecutor.java
@@ -0,0 +1,44 @@
+/*
+ * 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 com.sphereex.dbplusengine.proxy.backend.handler.distsql.ral.updatable;
+
+import 
com.sphereex.dbplusengine.distsql.statement.ral.updatable.DropLastExecuteFailedNodeStatement;
+import 
org.apache.shardingsphere.distsql.handler.engine.update.DistSQLUpdateExecutor;
+import 
org.apache.shardingsphere.distsql.handler.required.DistSQLExecutorClusterModeRequired;
+import org.apache.shardingsphere.mode.manager.ContextManager;
+
+import java.sql.SQLException;
+import java.util.Collection;
+
+/**
+ * Drop last execute failed node executor.
+ */
+@DistSQLExecutorClusterModeRequired
+public final class DropLastExecuteFailedNodeExecutor implements 
DistSQLUpdateExecutor<DropLastExecuteFailedNodeStatement> {
+    
+    @Override
+    public void executeUpdate(final DropLastExecuteFailedNodeStatement 
sqlStatement, final ContextManager contextManager) throws SQLException {
+        Collection<String> droppedInstanceIds = 
sqlStatement.getDroppedInstanceIds();
+        droppedInstanceIds.forEach(each -> 
contextManager.getPersistServiceFacade().getConsistencyPersistService().removeUnAckedConsistencyAckRecord(each));
+    }
+    
+    @Override
+    public Class<DropLastExecuteFailedNodeStatement> getType() {
+        return DropLastExecuteFailedNodeStatement.class;
+    }
+}
diff --git 
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/connector/DatabaseConnector.java
 
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/connector/DatabaseConnector.java
index 39c7763b609..b0dafc57849 100644
--- 
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/connector/DatabaseConnector.java
+++ 
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/connector/DatabaseConnector.java
@@ -17,6 +17,8 @@
 
 package org.apache.shardingsphere.proxy.backend.connector;
 
+import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.shardingsphere.infra.binder.context.aware.CursorAware;
 import 
org.apache.shardingsphere.infra.binder.context.segment.insert.keygen.GeneratedKeyContext;
 import 
org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
@@ -95,6 +97,10 @@ import java.util.stream.Collectors;
 /**
  * Database connector.
  */
+// SPEX ADDED: BEGIN
+@Getter
+@Slf4j
+// SPEX ADDED: END
 public final class DatabaseConnector implements DatabaseBackendHandler {
     
     private final String driverType;
diff --git 
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/database/DatabaseOperateBackendHandlerFactory.java
 
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/database/DatabaseOperateBackendHandlerFactory.java
index 5ab05c6a293..b97fd06796a 100644
--- 
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/database/DatabaseOperateBackendHandlerFactory.java
+++ 
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/database/DatabaseOperateBackendHandlerFactory.java
@@ -17,9 +17,12 @@
 
 package org.apache.shardingsphere.proxy.backend.handler.database;
 
+import 
com.sphereex.dbplusengine.infra.exception.metadata.MetaDataInconsistentException;
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
+import 
org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions;
 import 
org.apache.shardingsphere.infra.exception.generic.UnsupportedSQLOperationException;
+import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
 import org.apache.shardingsphere.proxy.backend.handler.ProxyBackendHandler;
 import org.apache.shardingsphere.proxy.backend.session.ConnectionSession;
 import 
org.apache.shardingsphere.sql.parser.statement.core.statement.SQLStatement;
@@ -44,6 +47,9 @@ public final class DatabaseOperateBackendHandlerFactory {
     }
     
     private static ProxyBackendHandler createBackendHandler(final SQLStatement 
sqlStatement, final ConnectionSession connectionSession) {
+        // SPEX ADDED: BEGIN
+        
ShardingSpherePreconditions.checkState(ProxyContext.getInstance().getContextManager().isMetaDataConsistent(),
 MetaDataInconsistentException::new);
+        // SPEX ADDED: END
         if (sqlStatement instanceof CreateDatabaseStatement) {
             return new CreateDatabaseBackendHandler((CreateDatabaseStatement) 
sqlStatement);
         }
diff --git 
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/database/DropDatabaseBackendHandler.java
 
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/database/DropDatabaseBackendHandler.java
index 3d80f30a58e..21c5a19589a 100644
--- 
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/database/DropDatabaseBackendHandler.java
+++ 
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/database/DropDatabaseBackendHandler.java
@@ -18,6 +18,10 @@
 package org.apache.shardingsphere.proxy.backend.handler.database;
 
 import com.google.common.base.Strings;
+import com.sphereex.dbplusengine.SphereEx;
+import com.sphereex.dbplusengine.infra.exception.lock.DatabaseLockedException;
+import com.sphereex.dbplusengine.mode.lock.SphereExLockContext;
+import 
com.sphereex.dbplusengine.mode.lock.manager.definition.ResourceLockDefinitionFactory;
 import lombok.RequiredArgsConstructor;
 import org.apache.shardingsphere.authority.checker.AuthorityChecker;
 import org.apache.shardingsphere.authority.rule.AuthorityRule;
@@ -26,6 +30,7 @@ import 
org.apache.shardingsphere.infra.database.core.type.DatabaseTypeRegistry;
 import 
org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions;
 import 
org.apache.shardingsphere.infra.exception.dialect.exception.syntax.database.DatabaseDropNotExistsException;
 import 
org.apache.shardingsphere.infra.exception.dialect.exception.syntax.database.UnknownDatabaseException;
+import org.apache.shardingsphere.infra.lock.LockContext;
 import org.apache.shardingsphere.infra.metadata.user.Grantee;
 import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
 import org.apache.shardingsphere.proxy.backend.handler.ProxyBackendHandler;
@@ -65,6 +70,9 @@ public final class DropDatabaseBackendHandler implements 
ProxyBackendHandler {
         AuthorityChecker authorityChecker = new 
AuthorityChecker(authorityRule, grantee);
         
ShardingSpherePreconditions.checkState(authorityChecker.isAuthorized(databaseName),
 () -> new UnknownDatabaseException(databaseName));
         ShardingSpherePreconditions.checkState(sqlStatement.isIfExists() || 
ProxyContext.getInstance().databaseExists(databaseName), () -> new 
DatabaseDropNotExistsException(databaseName));
+        // SPEX ADDED: BEGIN
+        checkDatabaseLocked(databaseName);
+        // SPEX ADDED: END
     }
     
     private boolean isDropCurrentDatabase(final String databaseName) {
@@ -75,4 +83,12 @@ public final class DropDatabaseBackendHandler implements 
ProxyBackendHandler {
         DialectDatabaseMetaData dialectDatabaseMetaData = new 
DatabaseTypeRegistry(connectionSession.getProtocolType()).getDialectDatabaseMetaData();
         
ShardingSpherePreconditions.checkState(!dialectDatabaseMetaData.getDefaultSchema().isPresent(),
 () -> new UnsupportedOperationException("cannot drop the currently open 
database"));
     }
+
+    @SphereEx
+    @SuppressWarnings("rawtypes")
+    private void checkDatabaseLocked(final String databaseName) {
+        LockContext lockContext = 
ProxyContext.getInstance().getContextManager().getComputeNodeInstanceContext().getLockContext();
+        ShardingSpherePreconditions.checkState(!(lockContext instanceof 
SphereExLockContext) || 
!lockContext.isLocked(ResourceLockDefinitionFactory.newDatabaseLockDefinition(databaseName)),
+                () -> new DatabaseLockedException(databaseName));
+    }
 }
diff --git 
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/DistSQLBackendHandlerFactory.java
 
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/DistSQLBackendHandlerFactory.java
index bae9e5843ac..9ee0ab32d25 100644
--- 
a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/DistSQLBackendHandlerFactory.java
+++ 
b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/DistSQLBackendHandlerFactory.java
@@ -17,15 +17,27 @@
 
 package org.apache.shardingsphere.proxy.backend.handler.distsql;
 
+import com.sphereex.dbplusengine.SphereEx;
+import 
com.sphereex.dbplusengine.distsql.statement.ral.lock.UnlockDistLockStatement;
+import 
com.sphereex.dbplusengine.distsql.statement.ral.updatable.DropLastExecuteFailedNodeStatement;
+import com.sphereex.dbplusengine.infra.exception.lock.DatabaseLockedException;
+import 
com.sphereex.dbplusengine.infra.exception.metadata.MetaDataInconsistentException;
+import com.sphereex.dbplusengine.mode.lock.SphereExLockContext;
+import 
com.sphereex.dbplusengine.mode.lock.manager.definition.ResourceLockDefinitionFactory;
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
+import 
org.apache.shardingsphere.data.pipeline.distsql.statement.updatable.UpdatablePipelineRALStatement;
 import org.apache.shardingsphere.distsql.statement.DistSQLStatement;
 import org.apache.shardingsphere.distsql.statement.ral.RALStatement;
 import 
org.apache.shardingsphere.distsql.statement.ral.queryable.QueryableRALStatement;
+import 
org.apache.shardingsphere.distsql.statement.ral.updatable.UpdatableRALStatement;
 import org.apache.shardingsphere.distsql.statement.rdl.RDLStatement;
 import org.apache.shardingsphere.distsql.statement.rql.RQLStatement;
 import org.apache.shardingsphere.distsql.statement.rul.RULStatement;
+import 
org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions;
 import 
org.apache.shardingsphere.infra.exception.generic.UnsupportedSQLOperationException;
+import org.apache.shardingsphere.infra.lock.LockContext;
+import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
 import org.apache.shardingsphere.proxy.backend.handler.ProxyBackendHandler;
 import org.apache.shardingsphere.proxy.backend.session.ConnectionSession;
 
@@ -48,11 +60,41 @@ public final class DistSQLBackendHandlerFactory {
             return new DistSQLQueryBackendHandler(sqlStatement, 
connectionSession);
         }
         if (sqlStatement instanceof RDLStatement) {
+            // SPEX ADDED: BEGIN
+            checkConsistencyState(sqlStatement);
+            checkDatabaseLocked(connectionSession, sqlStatement);
+            // SPEX ADDED: END
             return new DistSQLUpdateBackendHandler(sqlStatement, 
connectionSession);
         }
         if (sqlStatement instanceof RALStatement) {
+            // SPEX ADDED: BEGIN
+            if (sqlStatement instanceof UpdatableRALStatement && 
!(sqlStatement instanceof UpdatablePipelineRALStatement)) {
+                checkConsistencyState(sqlStatement);
+                checkDatabaseLocked(connectionSession, sqlStatement);
+            }
+            // SPEX ADDED: END
             return sqlStatement instanceof QueryableRALStatement ? new 
DistSQLQueryBackendHandler(sqlStatement, connectionSession) : new 
DistSQLUpdateBackendHandler(sqlStatement, connectionSession);
         }
         throw new 
UnsupportedSQLOperationException(sqlStatement.getClass().getName());
     }
+
+    @SphereEx
+    @SuppressWarnings("rawtypes")
+    private static void checkDatabaseLocked(final ConnectionSession 
connectionSession, final DistSQLStatement sqlStatement) {
+        if (null == connectionSession.getUsedDatabaseName() || sqlStatement 
instanceof UnlockDistLockStatement) {
+            return;
+        }
+        LockContext lockContext = 
ProxyContext.getInstance().getContextManager().getComputeNodeInstanceContext().getLockContext();
+        if (lockContext instanceof SphereExLockContext && 
lockContext.isLocked(ResourceLockDefinitionFactory.newDatabaseLockDefinition(connectionSession.getUsedDatabaseName())))
 {
+            throw new 
DatabaseLockedException(connectionSession.getUsedDatabaseName(), "can not be 
updated by DistSQL");
+        }
+    }
+
+    @SphereEx
+    private static void checkConsistencyState(final DistSQLStatement 
sqlStatement) {
+        if (sqlStatement instanceof UnlockDistLockStatement || sqlStatement 
instanceof DropLastExecuteFailedNodeStatement) {
+            return;
+        }
+        
ShardingSpherePreconditions.checkState(ProxyContext.getInstance().getContextManager().isMetaDataConsistent(),
 MetaDataInconsistentException::new);
+    }
 }
diff --git 
a/proxy/backend/core/src/main/resources/META-INF/services/org.apache.shardingsphere.distsql.handler.engine.query.DistSQLQueryExecutor
 
b/proxy/backend/core/src/main/resources/META-INF/services/org.apache.shardingsphere.distsql.handler.engine.query.DistSQLQueryExecutor
index 0fd9be4cca3..07b94c2aaab 100644
--- 
a/proxy/backend/core/src/main/resources/META-INF/services/org.apache.shardingsphere.distsql.handler.engine.query.DistSQLQueryExecutor
+++ 
b/proxy/backend/core/src/main/resources/META-INF/services/org.apache.shardingsphere.distsql.handler.engine.query.DistSQLQueryExecutor
@@ -28,3 +28,6 @@ 
org.apache.shardingsphere.proxy.backend.handler.distsql.ral.queryable.ShowTableM
 org.apache.shardingsphere.proxy.backend.handler.distsql.rul.FormatSQLExecutor
 
org.apache.shardingsphere.proxy.backend.handler.distsql.rul.ParseDistSQLExecutor
 org.apache.shardingsphere.proxy.backend.handler.distsql.rul.PreviewExecutor
+
+com.sphereex.dbplusengine.proxy.backend.handler.distsql.ral.lock.ShowDistLocksExecutor
+com.sphereex.dbplusengine.proxy.backend.handler.distsql.ral.queryable.ShowLastExecuteFailedNodesExecutor
diff --git 
a/proxy/backend/core/src/main/resources/META-INF/services/org.apache.shardingsphere.distsql.handler.engine.update.DistSQLUpdateExecutor
 
b/proxy/backend/core/src/main/resources/META-INF/services/org.apache.shardingsphere.distsql.handler.engine.update.DistSQLUpdateExecutor
index 7deb228ccb2..ff59bceec8b 100644
--- 
a/proxy/backend/core/src/main/resources/META-INF/services/org.apache.shardingsphere.distsql.handler.engine.update.DistSQLUpdateExecutor
+++ 
b/proxy/backend/core/src/main/resources/META-INF/services/org.apache.shardingsphere.distsql.handler.engine.update.DistSQLUpdateExecutor
@@ -25,3 +25,6 @@ 
org.apache.shardingsphere.proxy.backend.handler.distsql.ral.updatable.RefreshDat
 
org.apache.shardingsphere.proxy.backend.handler.distsql.ral.updatable.LockClusterExecutor
 
org.apache.shardingsphere.proxy.backend.handler.distsql.ral.updatable.UnlockClusterExecutor
 
org.apache.shardingsphere.proxy.backend.handler.distsql.ral.updatable.RefreshTableMetaDataExecutor
+
+com.sphereex.dbplusengine.proxy.backend.handler.distsql.ral.lock.UnlockDistLockStatementExecutor
+com.sphereex.dbplusengine.proxy.backend.handler.distsql.ral.updatable.DropLastExecuteFailedNodeExecutor
diff --git 
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/ProxyBackendHandlerFactoryTest.java
 
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/ProxyBackendHandlerFactoryTest.java
index ed179228666..21c60c7388a 100644
--- 
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/ProxyBackendHandlerFactoryTest.java
+++ 
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/ProxyBackendHandlerFactoryTest.java
@@ -120,6 +120,9 @@ class ProxyBackendHandlerFactoryTest {
         ContextManager result = mock(ContextManager.class, RETURNS_DEEP_STUBS);
         when(result.getMetaDataContexts()).thenReturn(metaDataContexts);
         when(metaDataContexts.getMetaData().getProps()).thenReturn(new 
ConfigurationProperties(new Properties()));
+        // SPEX ADDED: BEGIN
+        when(result.isMetaDataConsistent()).thenReturn(true);
+        // SPEX ADDED: END
         RuleMetaData globalRuleMetaData = new RuleMetaData(Arrays.asList(
                 new AuthorityRule(new 
DefaultAuthorityRuleConfigurationBuilder().build()),
                 new SQLParserRule(new 
DefaultSQLParserRuleConfigurationBuilder().build()),
diff --git 
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/database/DatabaseOperateBackendHandlerFactoryTest.java
 
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/database/DatabaseOperateBackendHandlerFactoryTest.java
index 3a9ccc62d66..c237b69a5c4 100644
--- 
a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/database/DatabaseOperateBackendHandlerFactoryTest.java
+++ 
b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/database/DatabaseOperateBackendHandlerFactoryTest.java
@@ -85,6 +85,9 @@ class DatabaseOperateBackendHandlerFactoryTest {
         
when(contextManager.getMetaDataContexts()).thenReturn(metaDataContexts);
         
when(ProxyContext.getInstance().getContextManager()).thenReturn(contextManager);
         
when(ProxyContext.getInstance().databaseExists("foo_db")).thenReturn(true);
+        // SPEX ADDED: BEGIN
+        when(contextManager.isMetaDataConsistent()).thenReturn(true);
+        // SPEX ADDED: END
     }
     
     @AfterEach
diff --git a/proxy/backend/pom.xml b/proxy/backend/enterprise/pom.xml
similarity index 75%
copy from proxy/backend/pom.xml
copy to proxy/backend/enterprise/pom.xml
index ece6cb31c42..f52581e403c 100644
--- a/proxy/backend/pom.xml
+++ b/proxy/backend/enterprise/pom.xml
@@ -20,15 +20,18 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.apache.shardingsphere</groupId>
-        <artifactId>shardingsphere-proxy</artifactId>
+        <artifactId>shardingsphere-proxy-backend</artifactId>
         <version>5.5.1-SNAPSHOT</version>
     </parent>
-    <artifactId>shardingsphere-proxy-backend</artifactId>
-    <packaging>pom</packaging>
+    <groupId>com.sphere-ex</groupId>
+    <artifactId>dbplusengine-proxy-backend-enterprise</artifactId>
     <name>${project.artifactId}</name>
     
-    <modules>
-        <module>core</module>
-        <module>type</module>
-    </modules>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.shardingsphere</groupId>
+            <artifactId>shardingsphere-proxy-backend-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
 </project>
diff --git 
a/proxy/backend/enterprise/src/main/java/com/sphereex/dbplusengine/proxy/backend/enterprise/connector/EnterpriseAdvancedProxySQLExecutor.java
 
b/proxy/backend/enterprise/src/main/java/com/sphereex/dbplusengine/proxy/backend/enterprise/connector/EnterpriseAdvancedProxySQLExecutor.java
new file mode 100644
index 00000000000..7a2c642a960
--- /dev/null
+++ 
b/proxy/backend/enterprise/src/main/java/com/sphereex/dbplusengine/proxy/backend/enterprise/connector/EnterpriseAdvancedProxySQLExecutor.java
@@ -0,0 +1,101 @@
+/*
+ * 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 com.sphereex.dbplusengine.proxy.backend.enterprise.connector;
+
+import com.sphereex.dbplusengine.infra.exception.lock.LockWaitTimeoutException;
+import com.sphereex.dbplusengine.infra.exception.lock.TableLockedException;
+import 
com.sphereex.dbplusengine.infra.exception.metadata.MetaDataInconsistentException;
+import com.sphereex.dbplusengine.mode.lock.ResourceLockDefinitionManager;
+import com.sphereex.dbplusengine.mode.lock.checker.SphereExLockChecker;
+import 
com.sphereex.dbplusengine.mode.lock.manager.definition.ResourceLockDefinition;
+import 
org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
+import org.apache.shardingsphere.infra.binder.context.type.TableAvailable;
+import 
org.apache.shardingsphere.infra.config.props.temporary.TemporaryConfigurationPropertyKey;
+import org.apache.shardingsphere.infra.database.core.type.DatabaseTypeRegistry;
+import 
org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions;
+import org.apache.shardingsphere.infra.executor.sql.context.ExecutionContext;
+import 
org.apache.shardingsphere.infra.executor.sql.execute.result.ExecuteResult;
+import org.apache.shardingsphere.infra.lock.GlobalLockNames;
+import 
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
+import org.apache.shardingsphere.mode.lock.GlobalLockDefinition;
+import org.apache.shardingsphere.mode.manager.ContextManager;
+import org.apache.shardingsphere.mode.metadata.refresher.MetaDataRefreshEngine;
+import 
org.apache.shardingsphere.proxy.backend.connector.AdvancedProxySQLExecutor;
+import org.apache.shardingsphere.proxy.backend.connector.DatabaseConnector;
+import 
org.apache.shardingsphere.proxy.backend.connector.jdbc.transaction.BackendTransactionManager;
+import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
+
+import java.sql.SQLException;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Advanced proxy SQL executor for enterprise.
+ */
+public final class EnterpriseAdvancedProxySQLExecutor implements 
AdvancedProxySQLExecutor {
+    
+    @Override
+    public List<ExecuteResult> execute(final ExecutionContext 
executionContext, final ContextManager contextManager,
+                                       final ShardingSphereDatabase database, 
final DatabaseConnector databaseConnector) throws SQLException {
+        try {
+            new 
SphereExLockChecker(contextManager.getComputeNodeInstanceContext().getLockContext(),
+                    
contextManager.getMetaDataContexts().getMetaData().getTemporaryProps()).checkUnlock(database.getName(),
 executionContext.getSqlStatementContext());
+        } catch (final TableLockedException ex) {
+            if 
(databaseConnector.getDatabaseConnectionManager().getConnectionSession().getTransactionStatus().isInTransaction())
 {
+                new 
BackendTransactionManager(databaseConnector.getDatabaseConnectionManager()).rollback();
+            }
+            throw ex;
+        }
+        if 
(MetaDataRefreshEngine.isRefreshMetaDataRequired(executionContext.getSqlStatementContext()))
 {
+            Optional<ResourceLockDefinitionManager> 
resourceLockDefinitionManager = 
contextManager.getResourceLockDefinitionManager();
+            return resourceLockDefinitionManager.isPresent()
+                    ? executeLockDDL(resourceLockDefinitionManager.get(), 
executionContext, database, databaseConnector, contextManager)
+                    : 
databaseConnector.getProxySQLExecutor().execute(executionContext);
+        }
+        return 
databaseConnector.getProxySQLExecutor().execute(executionContext);
+    }
+    
+    private List<ExecuteResult> executeLockDDL(final 
ResourceLockDefinitionManager lockDefinitionManager, final ExecutionContext 
executionContext,
+                                               final ShardingSphereDatabase 
database, final DatabaseConnector databaseConnector, final ContextManager 
contextManager) throws SQLException {
+        
ShardingSpherePreconditions.checkState(ProxyContext.getInstance().getContextManager().isMetaDataConsistent(),
 MetaDataInconsistentException::new);
+        GlobalLockDefinition globalLockDefinition = new 
GlobalLockDefinition(GlobalLockNames.UPDATE_METADATA.getLockName());
+        long timeout = 
contextManager.getMetaDataContexts().getMetaData().getTemporaryProps().<Long>getValue(TemporaryConfigurationPropertyKey.LOCK_TIME_OUT_MILLISECONDS);
+        if 
(!contextManager.getComputeNodeInstanceContext().getLockContext().tryLock(globalLockDefinition,
 timeout)) {
+            throw new 
LockWaitTimeoutException(GlobalLockNames.UPDATE_METADATA, timeout);
+        }
+        ResourceLockDefinition resourceLockDefinition = null;
+        try {
+            SQLStatementContext sqlStatementContext = 
executionContext.getSqlStatementContext();
+            if (sqlStatementContext instanceof TableAvailable) {
+                String schemaName = ((TableAvailable) 
sqlStatementContext).getTablesContext().getSchemaName()
+                        .orElseGet(() -> new 
DatabaseTypeRegistry(sqlStatementContext.getDatabaseType()).getDefaultSchemaName(database.getName()));
+                Collection<String> tableNames = new 
HashSet<>(((TableAvailable) 
sqlStatementContext).getTablesContext().getTableNames());
+                resourceLockDefinition = 
lockDefinitionManager.tryLock(database.getName(), schemaName, tableNames);
+            } else {
+                String schemaName = new 
DatabaseTypeRegistry(sqlStatementContext.getDatabaseType()).getDefaultSchemaName(database.getName());
+                resourceLockDefinition = 
lockDefinitionManager.tryLock(database.getName(), schemaName);
+            }
+            return 
databaseConnector.getProxySQLExecutor().execute(executionContext);
+        } finally {
+            
contextManager.getComputeNodeInstanceContext().getLockContext().unlock(globalLockDefinition);
+            lockDefinitionManager.unlock(resourceLockDefinition);
+        }
+    }
+}
diff --git 
a/proxy/backend/enterprise/src/main/java/com/sphereex/dbplusengine/proxy/backend/enterprise/handler/distsql/ral/updatable/LockRequiredRefreshTableMetaDataExecutor.java
 
b/proxy/backend/enterprise/src/main/java/com/sphereex/dbplusengine/proxy/backend/enterprise/handler/distsql/ral/updatable/LockRequiredRefreshTableMetaDataExecutor.java
new file mode 100644
index 00000000000..c689740a8de
--- /dev/null
+++ 
b/proxy/backend/enterprise/src/main/java/com/sphereex/dbplusengine/proxy/backend/enterprise/handler/distsql/ral/updatable/LockRequiredRefreshTableMetaDataExecutor.java
@@ -0,0 +1,73 @@
+/*
+ * 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 
com.sphereex.dbplusengine.proxy.backend.enterprise.handler.distsql.ral.updatable;
+
+import com.sphereex.dbplusengine.mode.lock.ResourceLockDefinitionManager;
+import 
com.sphereex.dbplusengine.mode.lock.manager.definition.ResourceLockDefinition;
+import lombok.Setter;
+import 
org.apache.shardingsphere.distsql.handler.aware.DistSQLExecutorDatabaseAware;
+import 
org.apache.shardingsphere.distsql.handler.engine.update.AdvancedDistSQLUpdateExecutor;
+import 
org.apache.shardingsphere.distsql.statement.ral.updatable.RefreshTableMetaDataStatement;
+import org.apache.shardingsphere.infra.database.core.type.DatabaseTypeRegistry;
+import 
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
+import org.apache.shardingsphere.mode.manager.ContextManager;
+import 
org.apache.shardingsphere.proxy.backend.handler.distsql.ral.updatable.RefreshTableMetaDataExecutor;
+
+import java.sql.SQLException;
+import java.util.Optional;
+
+/**
+ * Lock required refresh table meta data executor.
+ */
+@Setter
+public final class LockRequiredRefreshTableMetaDataExecutor implements 
AdvancedDistSQLUpdateExecutor<RefreshTableMetaDataStatement>, 
DistSQLExecutorDatabaseAware {
+    
+    private ShardingSphereDatabase database;
+    
+    @Override
+    public void executeUpdate(final RefreshTableMetaDataStatement 
sqlStatement, final ContextManager contextManager) throws SQLException {
+        Optional<ResourceLockDefinitionManager> lockDefinitionManager = 
contextManager.getResourceLockDefinitionManager();
+        RefreshTableMetaDataExecutor refreshTableMetaDataExecutor = new 
RefreshTableMetaDataExecutor();
+        refreshTableMetaDataExecutor.setDatabase(database);
+        ResourceLockDefinition resourceLockDefinition = 
lockDefinitionManager.map(optional -> tryLock(optional, 
sqlStatement)).orElse(null);
+        try {
+            refreshTableMetaDataExecutor.executeUpdate(sqlStatement, 
contextManager);
+        } finally {
+            lockDefinitionManager.ifPresent(optional -> 
optional.unlock(resourceLockDefinition));
+        }
+    }
+    
+    private ResourceLockDefinition tryLock(final ResourceLockDefinitionManager 
lockManager, final RefreshTableMetaDataStatement sqlStatement) {
+        if (sqlStatement.getTableName().isPresent()) {
+            return lockManager.tryLock(database.getName(), 
getSchemaName(sqlStatement), sqlStatement.getTableName().get());
+        }
+        if (sqlStatement.getStorageUnitName().isPresent()) {
+            return lockManager.tryLock(database.getName(), 
getSchemaName(sqlStatement));
+        }
+        return lockManager.tryLock(database.getName());
+    }
+    
+    private String getSchemaName(final RefreshTableMetaDataStatement 
sqlStatement) {
+        return sqlStatement.getSchemaName().isPresent() ? 
sqlStatement.getSchemaName().get() : new 
DatabaseTypeRegistry(database.getProtocolType()).getDefaultSchemaName(database.getName());
+    }
+    
+    @Override
+    public Class<RefreshTableMetaDataStatement> getType() {
+        return RefreshTableMetaDataStatement.class;
+    }
+}
diff --git 
a/proxy/backend/enterprise/src/main/resources/META-INF/services/org.apache.shardingsphere.distsql.handler.engine.update.AdvancedDistSQLUpdateExecutor
 
b/proxy/backend/enterprise/src/main/resources/META-INF/services/org.apache.shardingsphere.distsql.handler.engine.update.AdvancedDistSQLUpdateExecutor
new file mode 100644
index 00000000000..ca90a1bfa42
--- /dev/null
+++ 
b/proxy/backend/enterprise/src/main/resources/META-INF/services/org.apache.shardingsphere.distsql.handler.engine.update.AdvancedDistSQLUpdateExecutor
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+com.sphereex.dbplusengine.proxy.backend.enterprise.handler.distsql.ral.updatable.LockRequiredRefreshTableMetaDataExecutor
diff --git 
a/proxy/backend/enterprise/src/main/resources/META-INF/services/org.apache.shardingsphere.proxy.backend.connector.AdvancedProxySQLExecutor
 
b/proxy/backend/enterprise/src/main/resources/META-INF/services/org.apache.shardingsphere.proxy.backend.connector.AdvancedProxySQLExecutor
new file mode 100644
index 00000000000..1025623109c
--- /dev/null
+++ 
b/proxy/backend/enterprise/src/main/resources/META-INF/services/org.apache.shardingsphere.proxy.backend.connector.AdvancedProxySQLExecutor
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+com.sphereex.dbplusengine.proxy.backend.enterprise.connector.EnterpriseAdvancedProxySQLExecutor
diff --git a/proxy/backend/pom.xml b/proxy/backend/pom.xml
index ece6cb31c42..bf783108a8c 100644
--- a/proxy/backend/pom.xml
+++ b/proxy/backend/pom.xml
@@ -30,5 +30,8 @@
     <modules>
         <module>core</module>
         <module>type</module>
+        <!-- SPEX ADDED: BEGIN -->
+        <module>enterprise</module>
+        <!-- SPEX ADDED: END -->
     </modules>
 </project>

Reply via email to