You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by pa...@apache.org on 2020/10/18 13:53:31 UTC

[shardingsphere] branch master updated: support create table without rule configuration (#7831)

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

panjuan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git


The following commit(s) were added to refs/heads/master by this push:
     new 8c41e75  support create table without rule configuration (#7831)
8c41e75 is described below

commit 8c41e756b58cf10b38a6916106dc347a4c34d82d
Author: DuanZhengqiang <st...@gmail.com>
AuthorDate: Sun Oct 18 21:52:59 2020 +0800

    support create table without rule configuration (#7831)
---
 .../engine/type/ShardingRouteEngineFactory.java    | 24 +++++---
 .../ShardingUnconfiguredTablesRoutingEngine.java   | 13 +++-
 ...hardingUnconfiguredTablesRoutingEngineTest.java | 33 +++++++---
 .../metadata/refresh/MetaDataRefreshStrategy.java  |  7 +--
 ...AlterTableStatementMetaDataRefreshStrategy.java | 11 ++--
 ...reateIndexStatementMetaDataRefreshStrategy.java |  9 ++-
 ...reateTableStatementMetaDataRefreshStrategy.java | 17 +++---
 .../DropIndexStatementMetaDataRefreshStrategy.java | 10 ++--
 .../DropTableStatementMetaDataRefreshStrategy.java | 17 ++++--
 ...rTableStatementMetaDataRefreshStrategyTest.java | 12 ++--
 ...eIndexStatementMetaDataRefreshStrategyTest.java | 20 +++----
 ...eTableStatementMetaDataRefreshStrategyTest.java | 70 ++++++----------------
 ...pIndexStatementMetaDataRefreshStrategyTest.java |  4 +-
 ...pTableStatementMetaDataRefreshStrategyTest.java | 44 ++++++++++++--
 .../driver/executor/AbstractStatementExecutor.java | 24 +++++---
 .../driver/executor/PreparedStatementExecutor.java | 10 ++--
 .../driver/executor/StatementExecutor.java         | 56 ++++++++++-------
 .../statement/ShardingSpherePreparedStatement.java |  4 +-
 .../core/statement/ShardingSphereStatement.java    | 16 ++---
 .../executor/PreparedStatementExecutorTest.java    | 32 +++++-----
 .../driver/executor/StatementExecutorTest.java     | 38 ++++++------
 .../jdbc/JDBCDatabaseCommunicationEngine.java      | 18 ++++--
 22 files changed, 274 insertions(+), 215 deletions(-)

diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/type/ShardingRouteEngineFactory.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/type/ShardingRouteEngineFactory.java
index 110fc59..4abc2c9 100644
--- a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/type/ShardingRouteEngineFactory.java
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/type/ShardingRouteEngineFactory.java
@@ -41,13 +41,16 @@ import org.apache.shardingsphere.sql.parser.sql.common.statement.dal.SetStatemen
 import org.apache.shardingsphere.sql.parser.sql.common.statement.dcl.DCLStatement;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.AlterFunctionStatement;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.AlterProcedureStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.AlterTableStatement;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.AlterViewStatement;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.CreateFunctionStatement;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.CreateProcedureStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.CreateTableStatement;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.CreateViewStatement;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.DDLStatement;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.DropFunctionStatement;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.DropProcedureStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.DropTableStatement;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.DropViewStatement;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DMLStatement;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
@@ -83,7 +86,7 @@ public final class ShardingRouteEngineFactory {
             return new ShardingDatabaseBroadcastRoutingEngine();
         }
         if (sqlStatement instanceof DDLStatement) {
-            return getDDLRoutingEngine(tableNames, metaData.getSchemaMetaData(), sqlStatementContext);
+            return getDDLRoutingEngine(shardingRule, metaData.getSchemaMetaData(), sqlStatementContext);
         }
         if (sqlStatement instanceof DALStatement) {
             return getDALRoutingEngine(shardingRule, metaData.getSchemaMetaData().getUnconfiguredSchemaMetaDataMap(), sqlStatement, tableNames);
@@ -98,24 +101,27 @@ public final class ShardingRouteEngineFactory {
             return new ShardingUnicastRoutingEngine(tableNames);
         }
         if (!shardingRule.tableRuleExists(tableNames)) {
-            return new ShardingUnconfiguredTablesRoutingEngine(tableNames, metaData.getSchemaMetaData().getUnconfiguredSchemaMetaDataMap());
+            return new ShardingUnconfiguredTablesRoutingEngine(tableNames, metaData.getSchemaMetaData().getUnconfiguredSchemaMetaDataMap(), sqlStatement);
         }
         return getShardingRoutingEngine(shardingRule, shardingConditions, tableNames, props);
     }
     
-    private static ShardingRouteEngine getDDLRoutingEngine(final Collection<String> tableNames, final LogicSchemaMetaData logicSchemaMetaData, final SQLStatementContext<?> sqlStatementContext) {
+    private static ShardingRouteEngine getDDLRoutingEngine(final ShardingRule shardingRule, final LogicSchemaMetaData schemaMetaData, final SQLStatementContext<?> sqlStatementContext) {
         SQLStatement sqlStatement = sqlStatementContext.getSqlStatement();
         boolean functionStatement = sqlStatement instanceof CreateFunctionStatement || sqlStatement instanceof AlterFunctionStatement || sqlStatement instanceof DropFunctionStatement;
         boolean procedureStatement = sqlStatement instanceof CreateProcedureStatement || sqlStatement instanceof AlterProcedureStatement || sqlStatement instanceof DropProcedureStatement;
         boolean viewStatement = sqlStatement instanceof CreateViewStatement || sqlStatement instanceof AlterViewStatement || sqlStatement instanceof DropViewStatement;
-        if (functionStatement || procedureStatement || viewStatement) {
-            return new ShardingUnconfiguredTablesRoutingEngine(tableNames, logicSchemaMetaData.getUnconfiguredSchemaMetaDataMap());
+        boolean tableStatement = sqlStatement instanceof CreateTableStatement || sqlStatement instanceof AlterTableStatement || sqlStatement instanceof DropTableStatement;
+        Collection<String> tableNames = sqlStatementContext.getTablesContext().getTableNames();
+        boolean modifyTableWithoutShardingRule = tableStatement && !tableNames.isEmpty() && !shardingRule.tableRuleExists(tableNames);
+        if (functionStatement || procedureStatement || viewStatement || modifyTableWithoutShardingRule) {
+            return new ShardingUnconfiguredTablesRoutingEngine(tableNames, schemaMetaData.getUnconfiguredSchemaMetaDataMap(), sqlStatement);
         }
-        return new ShardingTableBroadcastRoutingEngine(logicSchemaMetaData.getConfiguredSchemaMetaData(), sqlStatementContext);
+        return new ShardingTableBroadcastRoutingEngine(schemaMetaData.getConfiguredSchemaMetaData(), sqlStatementContext);
     }
     
-    private static ShardingRouteEngine getDALRoutingEngine(final ShardingRule shardingRule,
-                                                           final Map<String, Collection<String>> unconfiguredSchemaMetaDataMap, final SQLStatement sqlStatement, final Collection<String> tableNames) {
+    private static ShardingRouteEngine getDALRoutingEngine(final ShardingRule shardingRule, final Map<String, Collection<String>> unconfiguredSchemaMetaDataMap, 
+                                                           final SQLStatement sqlStatement, final Collection<String> tableNames) {
         if (sqlStatement instanceof MySQLUseStatement) {
             return new ShardingIgnoreRoutingEngine();
         }
@@ -123,7 +129,7 @@ public final class ShardingRouteEngineFactory {
             return new ShardingDatabaseBroadcastRoutingEngine();
         }
         if (!tableNames.isEmpty() && !shardingRule.tableRuleExists(tableNames)) {
-            return new ShardingUnconfiguredTablesRoutingEngine(tableNames, unconfiguredSchemaMetaDataMap);
+            return new ShardingUnconfiguredTablesRoutingEngine(tableNames, unconfiguredSchemaMetaDataMap, sqlStatement);
         }
         if (!tableNames.isEmpty()) {
             return new ShardingUnicastRoutingEngine(tableNames);
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/type/unconfigured/ShardingUnconfiguredTablesRoutingEngine.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/type/unconfigured/ShardingUnconfiguredTablesRoutingEngine.java
index c87c783..fefef35 100644
--- a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/type/unconfigured/ShardingUnconfiguredTablesRoutingEngine.java
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/type/unconfigured/ShardingUnconfiguredTablesRoutingEngine.java
@@ -17,6 +17,7 @@
 
 package org.apache.shardingsphere.sharding.route.engine.type.unconfigured;
 
+import com.google.common.collect.Lists;
 import lombok.RequiredArgsConstructor;
 import org.apache.shardingsphere.infra.exception.ShardingSphereException;
 import org.apache.shardingsphere.infra.route.context.RouteContext;
@@ -24,12 +25,15 @@ import org.apache.shardingsphere.infra.route.context.RouteMapper;
 import org.apache.shardingsphere.infra.route.context.RouteUnit;
 import org.apache.shardingsphere.sharding.route.engine.type.ShardingRouteEngine;
 import org.apache.shardingsphere.sharding.rule.ShardingRule;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.CreateTableStatement;
 
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Optional;
+import java.util.concurrent.ThreadLocalRandom;
 import java.util.stream.Collectors;
 
 /**
@@ -42,9 +46,11 @@ public final class ShardingUnconfiguredTablesRoutingEngine implements ShardingRo
     
     private final Map<String, Collection<String>> unconfiguredSchemaMetaDataMap;
     
+    private final SQLStatement sqlStatement;
+    
     @Override
     public void route(final RouteContext routeContext, final ShardingRule shardingRule) {
-        Optional<String> dataSourceName = findDataSourceName();
+        Optional<String> dataSourceName = sqlStatement instanceof CreateTableStatement ? getRandomDataSourceName(shardingRule.getDataSourceNames()) : findDataSourceName();
         if (!dataSourceName.isPresent()) {
             throw new ShardingSphereException("Can not route tables for `%s`, please make sure the tables are in same schema.", logicTables);
         }
@@ -60,4 +66,9 @@ public final class ShardingUnconfiguredTablesRoutingEngine implements ShardingRo
         }
         return Optional.empty();
     }
+    
+    private Optional<String> getRandomDataSourceName(final Collection<String> dataSourceNames) {
+        String dataSourceName = Lists.newArrayList(dataSourceNames).get(ThreadLocalRandom.current().nextInt(dataSourceNames.size()));
+        return Optional.of(dataSourceName);
+    }
 }
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/test/java/org/apache/shardingsphere/sharding/route/engine/type/unconfigured/ShardingUnconfiguredTablesRoutingEngineTest.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/test/java/org/apache/shardingsphere/sharding/route/engine/type/unconfigured/ShardingUnconfiguredTablesRoutingEngineTest.java
index 9bfa11c..67f3706 100644
--- a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/test/java/org/apache/shardingsphere/sharding/route/engine/type/unconfigured/ShardingUnconfiguredTablesRoutingEngineTest.java
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/test/java/org/apache/shardingsphere/sharding/route/engine/type/unconfigured/ShardingUnconfiguredTablesRoutingEngineTest.java
@@ -22,7 +22,7 @@ import org.apache.shardingsphere.infra.route.context.RouteMapper;
 import org.apache.shardingsphere.infra.route.context.RouteUnit;
 import org.apache.shardingsphere.sharding.api.config.ShardingRuleConfiguration;
 import org.apache.shardingsphere.sharding.rule.ShardingRule;
-import org.junit.Before;
+import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.ddl.MySQLCreateTableStatement;
 import org.junit.Test;
 
 import java.util.ArrayList;
@@ -38,24 +38,41 @@ import static org.junit.Assert.assertThat;
 
 public final class ShardingUnconfiguredTablesRoutingEngineTest {
     
-    private ShardingUnconfiguredTablesRoutingEngine shardingDefaultDatabaseRoutingEngine;
-    
-    @Before
-    public void setUp() {
+    @Test
+    public void assertRoute() {
         Map<String, Collection<String>> unconfiguredSchemaMetaDataMap = new HashMap<>(1, 1);
         unconfiguredSchemaMetaDataMap.put("ds_0", Arrays.asList("t_order", "t_order_item"));
-        shardingDefaultDatabaseRoutingEngine = new ShardingUnconfiguredTablesRoutingEngine(Arrays.asList("t_order", "t_order_item"), unconfiguredSchemaMetaDataMap);
+        ShardingUnconfiguredTablesRoutingEngine shardingDefaultDatabaseRoutingEngine 
+                = new ShardingUnconfiguredTablesRoutingEngine(Arrays.asList("t_order", "t_order_item"), unconfiguredSchemaMetaDataMap, null);
+        ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
+        ShardingRule shardingRule = new ShardingRule(shardingRuleConfig, Arrays.asList("ds_0", "ds_1"));
+        RouteContext routeContext = new RouteContext();
+        shardingDefaultDatabaseRoutingEngine.route(routeContext, shardingRule);
+        List<RouteUnit> routeUnits = new ArrayList<>(routeContext.getRouteUnits());
+        assertThat(routeContext.getRouteUnits().size(), is(1));
+        assertThat(routeUnits.get(0).getDataSourceMapper().getActualName(), is("ds_0"));
+        assertThat(routeUnits.get(0).getTableMappers().size(), is(2));
+        Iterator<RouteMapper> tableMappers = routeUnits.get(0).getTableMappers().iterator();
+        RouteMapper tableMapper0 = tableMappers.next();
+        assertThat(tableMapper0.getActualName(), is("t_order"));
+        assertThat(tableMapper0.getLogicName(), is("t_order"));
+        RouteMapper tableMapper1 = tableMappers.next();
+        assertThat(tableMapper1.getActualName(), is("t_order_item"));
+        assertThat(tableMapper1.getLogicName(), is("t_order_item"));
     }
     
     @Test
-    public void assertRoute() {
+    public void assertRouteWithoutShardingRule() {
+        Map<String, Collection<String>> unconfiguredSchemaMetaDataMap = new HashMap<>(1, 1);
+        unconfiguredSchemaMetaDataMap.put("ds_0", Arrays.asList("t_order", "t_order_item"));
+        ShardingUnconfiguredTablesRoutingEngine shardingDefaultDatabaseRoutingEngine 
+                = new ShardingUnconfiguredTablesRoutingEngine(Arrays.asList("t_order", "t_order_item"), unconfiguredSchemaMetaDataMap, new MySQLCreateTableStatement());
         ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
         ShardingRule shardingRule = new ShardingRule(shardingRuleConfig, Arrays.asList("ds_0", "ds_1"));
         RouteContext routeContext = new RouteContext();
         shardingDefaultDatabaseRoutingEngine.route(routeContext, shardingRule);
         List<RouteUnit> routeUnits = new ArrayList<>(routeContext.getRouteUnits());
         assertThat(routeContext.getRouteUnits().size(), is(1));
-        assertThat(routeUnits.get(0).getDataSourceMapper().getActualName(), is("ds_0"));
         assertThat(routeUnits.get(0).getTableMappers().size(), is(2));
         Iterator<RouteMapper> tableMappers = routeUnits.get(0).getTableMappers().iterator();
         RouteMapper tableMapper0 = tableMappers.next();
diff --git a/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/metadata/refresh/MetaDataRefreshStrategy.java b/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/metadata/refresh/MetaDataRefreshStrategy.java
index 005521e..6384a82 100644
--- a/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/metadata/refresh/MetaDataRefreshStrategy.java
+++ b/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/metadata/refresh/MetaDataRefreshStrategy.java
@@ -21,9 +21,8 @@ import org.apache.shardingsphere.infra.database.type.DatabaseType;
 import org.apache.shardingsphere.infra.metadata.model.ShardingSphereMetaData;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
 
-import javax.sql.DataSource;
 import java.sql.SQLException;
-import java.util.Map;
+import java.util.Collection;
 
 /**
  * Meta data refresh strategy.
@@ -37,10 +36,10 @@ public interface MetaDataRefreshStrategy<T extends SQLStatement> {
      *
      * @param metaData ShardingSphere meta data
      * @param databaseType database type
-     * @param dataSourceMap dataSource map
+     * @param routeDataSourceNames route dataSource names
      * @param sqlStatement SQL statement
      * @param callback callback
      * @throws SQLException SQL exception
      */
-    void refreshMetaData(ShardingSphereMetaData metaData, DatabaseType databaseType, Map<String, DataSource> dataSourceMap, T sqlStatement, TableMetaDataLoaderCallback callback) throws SQLException;
+    void refreshMetaData(ShardingSphereMetaData metaData, DatabaseType databaseType, Collection<String> routeDataSourceNames, T sqlStatement, TableMetaDataLoaderCallback callback) throws SQLException;
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/metadata/refresh/impl/AlterTableStatementMetaDataRefreshStrategy.java b/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/metadata/refresh/impl/AlterTableStatementMetaDataRefreshStrategy.java
index 2a79210..c37cc1d 100644
--- a/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/metadata/refresh/impl/AlterTableStatementMetaDataRefreshStrategy.java
+++ b/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/metadata/refresh/impl/AlterTableStatementMetaDataRefreshStrategy.java
@@ -17,17 +17,16 @@
 
 package org.apache.shardingsphere.infra.metadata.refresh.impl;
 
-import org.apache.shardingsphere.infra.metadata.model.physical.model.schema.PhysicalSchemaMetaData;
-import org.apache.shardingsphere.infra.metadata.model.physical.model.table.PhysicalTableMetaData;
 import org.apache.shardingsphere.infra.database.type.DatabaseType;
 import org.apache.shardingsphere.infra.metadata.model.ShardingSphereMetaData;
+import org.apache.shardingsphere.infra.metadata.model.physical.model.schema.PhysicalSchemaMetaData;
+import org.apache.shardingsphere.infra.metadata.model.physical.model.table.PhysicalTableMetaData;
 import org.apache.shardingsphere.infra.metadata.refresh.MetaDataRefreshStrategy;
 import org.apache.shardingsphere.infra.metadata.refresh.TableMetaDataLoaderCallback;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.AlterTableStatement;
 
-import javax.sql.DataSource;
 import java.sql.SQLException;
-import java.util.Map;
+import java.util.Collection;
 
 /**
  * Alter table statement meta data refresh strategy.
@@ -35,8 +34,8 @@ import java.util.Map;
 public final class AlterTableStatementMetaDataRefreshStrategy implements MetaDataRefreshStrategy<AlterTableStatement> {
     
     @Override
-    public void refreshMetaData(final ShardingSphereMetaData metaData, final DatabaseType databaseType,
-                                final Map<String, DataSource> dataSourceMap, final AlterTableStatement sqlStatement, final TableMetaDataLoaderCallback callback) throws SQLException {
+    public void refreshMetaData(final ShardingSphereMetaData metaData, final DatabaseType databaseType, final Collection<String> routeDataSourceNames, 
+                                final AlterTableStatement sqlStatement, final TableMetaDataLoaderCallback callback) throws SQLException {
         String tableName = sqlStatement.getTable().getTableName().getIdentifier().getValue();
         PhysicalSchemaMetaData schemaMetaData = metaData.getSchemaMetaData().getConfiguredSchemaMetaData();
         if (null != schemaMetaData && schemaMetaData.containsTable(tableName)) {
diff --git a/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/metadata/refresh/impl/CreateIndexStatementMetaDataRefreshStrategy.java b/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/metadata/refresh/impl/CreateIndexStatementMetaDataRefreshStrategy.java
index 77d4e9d..6db1a9e 100644
--- a/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/metadata/refresh/impl/CreateIndexStatementMetaDataRefreshStrategy.java
+++ b/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/metadata/refresh/impl/CreateIndexStatementMetaDataRefreshStrategy.java
@@ -17,15 +17,14 @@
 
 package org.apache.shardingsphere.infra.metadata.refresh.impl;
 
-import org.apache.shardingsphere.infra.metadata.model.physical.model.index.PhysicalIndexMetaData;
 import org.apache.shardingsphere.infra.database.type.DatabaseType;
 import org.apache.shardingsphere.infra.metadata.model.ShardingSphereMetaData;
+import org.apache.shardingsphere.infra.metadata.model.physical.model.index.PhysicalIndexMetaData;
 import org.apache.shardingsphere.infra.metadata.refresh.MetaDataRefreshStrategy;
 import org.apache.shardingsphere.infra.metadata.refresh.TableMetaDataLoaderCallback;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.CreateIndexStatement;
 
-import javax.sql.DataSource;
-import java.util.Map;
+import java.util.Collection;
 
 /**
  * Create index statement meta data refresh strategy.
@@ -33,8 +32,8 @@ import java.util.Map;
 public final class CreateIndexStatementMetaDataRefreshStrategy implements MetaDataRefreshStrategy<CreateIndexStatement> {
     
     @Override
-    public void refreshMetaData(final ShardingSphereMetaData metaData, final DatabaseType databaseType,
-                                final Map<String, DataSource> dataSourceMap, final CreateIndexStatement sqlStatement, final TableMetaDataLoaderCallback callback) {
+    public void refreshMetaData(final ShardingSphereMetaData metaData, final DatabaseType databaseType, final Collection<String> routeDataSourceNames, 
+                                final CreateIndexStatement sqlStatement, final TableMetaDataLoaderCallback callback) {
         if (null == sqlStatement.getIndex()) {
             return;
         }
diff --git a/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/metadata/refresh/impl/CreateTableStatementMetaDataRefreshStrategy.java b/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/metadata/refresh/impl/CreateTableStatementMetaDataRefreshStrategy.java
index 2977631..610262b 100644
--- a/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/metadata/refresh/impl/CreateTableStatementMetaDataRefreshStrategy.java
+++ b/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/metadata/refresh/impl/CreateTableStatementMetaDataRefreshStrategy.java
@@ -18,18 +18,15 @@
 package org.apache.shardingsphere.infra.metadata.refresh.impl;
 
 import com.google.common.collect.Lists;
-import org.apache.shardingsphere.infra.metadata.model.physical.model.table.PhysicalTableMetaData;
 import org.apache.shardingsphere.infra.database.type.DatabaseType;
 import org.apache.shardingsphere.infra.metadata.model.ShardingSphereMetaData;
+import org.apache.shardingsphere.infra.metadata.model.physical.model.table.PhysicalTableMetaData;
 import org.apache.shardingsphere.infra.metadata.refresh.MetaDataRefreshStrategy;
 import org.apache.shardingsphere.infra.metadata.refresh.TableMetaDataLoaderCallback;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.CreateTableStatement;
 
-import javax.sql.DataSource;
 import java.sql.SQLException;
 import java.util.Collection;
-import java.util.Map;
-import java.util.Map.Entry;
 import java.util.Optional;
 
 /**
@@ -38,22 +35,22 @@ import java.util.Optional;
 public final class CreateTableStatementMetaDataRefreshStrategy implements MetaDataRefreshStrategy<CreateTableStatement> {
     
     @Override
-    public void refreshMetaData(final ShardingSphereMetaData metaData, final DatabaseType databaseType,
-                                final Map<String, DataSource> dataSourceMap, final CreateTableStatement sqlStatement, final TableMetaDataLoaderCallback callback) throws SQLException {
+    public void refreshMetaData(final ShardingSphereMetaData metaData, final DatabaseType databaseType, final Collection<String> routeDataSourceNames, 
+                                final CreateTableStatement sqlStatement, final TableMetaDataLoaderCallback callback) throws SQLException {
         String tableName = sqlStatement.getTable().getTableName().getIdentifier().getValue();
         Optional<PhysicalTableMetaData> tableMetaData = callback.load(tableName);
         if (tableMetaData.isPresent()) {
             metaData.getSchemaMetaData().getConfiguredSchemaMetaData().put(tableName, tableMetaData.get());
             metaData.getSchemaMetaData().getSchemaMetaData().put(tableName, tableMetaData.get());
         } else {
-            refreshUnconfiguredMetaData(metaData, dataSourceMap, tableName);
+            refreshUnconfiguredMetaData(metaData, routeDataSourceNames, tableName);
             metaData.getSchemaMetaData().getSchemaMetaData().put(tableName, new PhysicalTableMetaData());
         }
     }
     
-    private void refreshUnconfiguredMetaData(final ShardingSphereMetaData metaData, final Map<String, DataSource> dataSourceMap, final String tableName) {
-        for (Entry<String, DataSource> entry : dataSourceMap.entrySet()) {
-            refreshUnconfiguredMetaData(metaData, tableName, entry.getKey());
+    private void refreshUnconfiguredMetaData(final ShardingSphereMetaData metaData, final Collection<String> routeDataSourceNames, final String tableName) {
+        for (String each : routeDataSourceNames) {
+            refreshUnconfiguredMetaData(metaData, tableName, each);
         }
     }
     
diff --git a/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/metadata/refresh/impl/DropIndexStatementMetaDataRefreshStrategy.java b/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/metadata/refresh/impl/DropIndexStatementMetaDataRefreshStrategy.java
index 7562ec1..5a2c0c3 100644
--- a/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/metadata/refresh/impl/DropIndexStatementMetaDataRefreshStrategy.java
+++ b/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/metadata/refresh/impl/DropIndexStatementMetaDataRefreshStrategy.java
@@ -17,20 +17,18 @@
 
 package org.apache.shardingsphere.infra.metadata.refresh.impl;
 
-import org.apache.shardingsphere.infra.metadata.model.physical.model.schema.PhysicalSchemaMetaData;
-import org.apache.shardingsphere.infra.metadata.model.physical.model.table.PhysicalTableMetaData;
 import org.apache.shardingsphere.infra.database.type.DatabaseType;
 import org.apache.shardingsphere.infra.metadata.model.ShardingSphereMetaData;
+import org.apache.shardingsphere.infra.metadata.model.physical.model.schema.PhysicalSchemaMetaData;
+import org.apache.shardingsphere.infra.metadata.model.physical.model.table.PhysicalTableMetaData;
 import org.apache.shardingsphere.infra.metadata.refresh.MetaDataRefreshStrategy;
 import org.apache.shardingsphere.infra.metadata.refresh.TableMetaDataLoaderCallback;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.DropIndexStatement;
 import org.apache.shardingsphere.sql.parser.sql.dialect.handler.ddl.DropIndexStatementHandler;
 
-import javax.sql.DataSource;
 import java.util.Collection;
 import java.util.LinkedList;
-import java.util.Map;
 import java.util.Optional;
 import java.util.stream.Collectors;
 
@@ -40,8 +38,8 @@ import java.util.stream.Collectors;
 public final class DropIndexStatementMetaDataRefreshStrategy implements MetaDataRefreshStrategy<DropIndexStatement> {
     
     @Override
-    public void refreshMetaData(final ShardingSphereMetaData metaData, final DatabaseType databaseType,
-                                final Map<String, DataSource> dataSourceMap, final DropIndexStatement sqlStatement, final TableMetaDataLoaderCallback callback) {
+    public void refreshMetaData(final ShardingSphereMetaData metaData, final DatabaseType databaseType, final Collection<String> routeDataSourceNames, 
+                                final DropIndexStatement sqlStatement, final TableMetaDataLoaderCallback callback) {
         Collection<String> indexNames = getIndexNames(sqlStatement);
         Optional<SimpleTableSegment> simpleTableSegment = DropIndexStatementHandler.getSimpleTableSegment(sqlStatement);
         String tableName = simpleTableSegment.map(tableSegment -> tableSegment.getTableName().getIdentifier().getValue()).orElse("");
diff --git a/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/metadata/refresh/impl/DropTableStatementMetaDataRefreshStrategy.java b/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/metadata/refresh/impl/DropTableStatementMetaDataRefreshStrategy.java
index a07f28a..e839592 100644
--- a/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/metadata/refresh/impl/DropTableStatementMetaDataRefreshStrategy.java
+++ b/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/metadata/refresh/impl/DropTableStatementMetaDataRefreshStrategy.java
@@ -23,8 +23,7 @@ import org.apache.shardingsphere.infra.metadata.refresh.MetaDataRefreshStrategy;
 import org.apache.shardingsphere.infra.metadata.refresh.TableMetaDataLoaderCallback;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.DropTableStatement;
 
-import javax.sql.DataSource;
-import java.util.Map;
+import java.util.Collection;
 
 /**
  * Drop table statement meta data refresh strategy.
@@ -32,13 +31,19 @@ import java.util.Map;
 public final class DropTableStatementMetaDataRefreshStrategy implements MetaDataRefreshStrategy<DropTableStatement> {
     
     @Override
-    public void refreshMetaData(final ShardingSphereMetaData metaData, final DatabaseType databaseType,
-                                final Map<String, DataSource> dataSourceMap, final DropTableStatement sqlStatement, final TableMetaDataLoaderCallback callback) {
-        sqlStatement.getTables().forEach(each -> removeMetaData(metaData, each.getTableName().getIdentifier().getValue()));
+    public void refreshMetaData(final ShardingSphereMetaData metaData, final DatabaseType databaseType, final Collection<String> routeDataSourceNames, 
+                                final DropTableStatement sqlStatement, final TableMetaDataLoaderCallback callback) {
+        sqlStatement.getTables().forEach(each -> removeMetaData(metaData, each.getTableName().getIdentifier().getValue(), routeDataSourceNames));
     }
     
-    private void removeMetaData(final ShardingSphereMetaData metaData, final String tableName) {
+    private void removeMetaData(final ShardingSphereMetaData metaData, final String tableName, final Collection<String> routeDataSourceNames) {
         metaData.getSchemaMetaData().getConfiguredSchemaMetaData().remove(tableName);
+        for (String each : routeDataSourceNames) {
+            Collection<String> schemaMetaData = metaData.getSchemaMetaData().getUnconfiguredSchemaMetaDataMap().get(each);
+            if (null != schemaMetaData) {
+                schemaMetaData.remove(tableName);
+            }
+        }
         metaData.getSchemaMetaData().getSchemaMetaData().remove(tableName);
     }
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-common/src/test/java/org/apache/shardingsphere/infra/metadata/refresh/impl/AlterTableStatementMetaDataRefreshStrategyTest.java b/shardingsphere-infra/shardingsphere-infra-common/src/test/java/org/apache/shardingsphere/infra/metadata/refresh/impl/AlterTableStatementMetaDataRefreshStrategyTest.java
index 46e3672..4197c98 100644
--- a/shardingsphere-infra/shardingsphere-infra-common/src/test/java/org/apache/shardingsphere/infra/metadata/refresh/impl/AlterTableStatementMetaDataRefreshStrategyTest.java
+++ b/shardingsphere-infra/shardingsphere-infra-common/src/test/java/org/apache/shardingsphere/infra/metadata/refresh/impl/AlterTableStatementMetaDataRefreshStrategyTest.java
@@ -44,34 +44,34 @@ import static org.mockito.Mockito.mock;
 public final class AlterTableStatementMetaDataRefreshStrategyTest extends AbstractMetaDataRefreshStrategyTest {
     
     @Test
-    public void refreshMySQLAlterTableMetaData() throws SQLException {
+    public void refreshMetaDataForMySQL() throws SQLException {
         refreshMetaData(new MySQLAlterTableStatement());
     }
 
     @Test
-    public void refreshOracleAlterTableMetaData() throws SQLException {
+    public void refreshMetaDataForOracle() throws SQLException {
         refreshMetaData(new OracleAlterTableStatement());
     }
 
     @Test
-    public void refreshPostgreSQLAlterTableMetaData() throws SQLException {
+    public void refreshMetaDataForPostgreSQL() throws SQLException {
         refreshMetaData(new PostgreSQLAlterTableStatement());
     }
 
     @Test
-    public void refreshSQL92AlterTableMetaData() throws SQLException {
+    public void refreshMetaDataForSQL92() throws SQLException {
         refreshMetaData(new SQL92AlterTableStatement());
     }
 
     @Test
-    public void refreshSQLServerAlterTableMetaData() throws SQLException {
+    public void refreshMetaDataForSQLServer() throws SQLException {
         refreshMetaData(new SQLServerAlterTableStatement());
     }
 
     private void refreshMetaData(final AlterTableStatement alterTableStatement) throws SQLException {
         MetaDataRefreshStrategy<AlterTableStatement> metaDataRefreshStrategy = new AlterTableStatementMetaDataRefreshStrategy();
         alterTableStatement.setTable(new SimpleTableSegment(new TableNameSegment(1, 3, new IdentifierValue("t_order"))));
-        metaDataRefreshStrategy.refreshMetaData(getMetaData(), mock(DatabaseType.class), Collections.emptyMap(), alterTableStatement, tableName -> Optional.of(new PhysicalTableMetaData(
+        metaDataRefreshStrategy.refreshMetaData(getMetaData(), mock(DatabaseType.class), Collections.emptyList(), alterTableStatement, tableName -> Optional.of(new PhysicalTableMetaData(
                 Collections.singletonList(new PhysicalColumnMetaData("order_id", 1, "String", true, false, false)),
                 Collections.singletonList(new PhysicalIndexMetaData("index_alter")))));
         assertTrue(getMetaData().getSchemaMetaData().getConfiguredSchemaMetaData().get("t_order").getIndexes().containsKey("index_alter"));
diff --git a/shardingsphere-infra/shardingsphere-infra-common/src/test/java/org/apache/shardingsphere/infra/metadata/refresh/impl/CreateIndexStatementMetaDataRefreshStrategyTest.java b/shardingsphere-infra/shardingsphere-infra-common/src/test/java/org/apache/shardingsphere/infra/metadata/refresh/impl/CreateIndexStatementMetaDataRefreshStrategyTest.java
index 8ab4aaa..667b61d 100644
--- a/shardingsphere-infra/shardingsphere-infra-common/src/test/java/org/apache/shardingsphere/infra/metadata/refresh/impl/CreateIndexStatementMetaDataRefreshStrategyTest.java
+++ b/shardingsphere-infra/shardingsphere-infra-common/src/test/java/org/apache/shardingsphere/infra/metadata/refresh/impl/CreateIndexStatementMetaDataRefreshStrategyTest.java
@@ -42,22 +42,22 @@ import static org.mockito.Mockito.mock;
 public final class CreateIndexStatementMetaDataRefreshStrategyTest extends AbstractMetaDataRefreshStrategyTest {
     
     @Test
-    public void refreshMySQLCreateIndexMetaData() throws SQLException {
+    public void refreshMetaDataForMySQL() throws SQLException {
         refreshMetaData(new MySQLCreateIndexStatement());
     }
     
     @Test
-    public void refreshOracleCreateIndexMetaData() throws SQLException {
+    public void refreshMetaDataForOracle() throws SQLException {
         refreshMetaData(new OracleCreateIndexStatement());
     }
     
     @Test
-    public void refreshPostgreSQLCreateIndexMetaData() throws SQLException {
+    public void refreshMetaDataForPostgreSQL() throws SQLException {
         refreshMetaData(new PostgreSQLCreateIndexStatement());
     }
     
     @Test
-    public void refreshSQLServerCreateIndexMetaData() throws SQLException {
+    public void refreshMetaDataForSQLServer() throws SQLException {
         refreshMetaData(new SQLServerCreateIndexStatement());
     }
     
@@ -65,34 +65,34 @@ public final class CreateIndexStatementMetaDataRefreshStrategyTest extends Abstr
         MetaDataRefreshStrategy<CreateIndexStatement> metaDataRefreshStrategy = new CreateIndexStatementMetaDataRefreshStrategy();
         createIndexStatement.setIndex(new IndexSegment(1, 2, new IdentifierValue("t_order_index")));
         createIndexStatement.setTable(new SimpleTableSegment(new TableNameSegment(1, 3, new IdentifierValue("t_order"))));
-        metaDataRefreshStrategy.refreshMetaData(getMetaData(), mock(DatabaseType.class), Collections.emptyMap(), createIndexStatement, tableName -> Optional.empty());
+        metaDataRefreshStrategy.refreshMetaData(getMetaData(), mock(DatabaseType.class), Collections.emptyList(), createIndexStatement, tableName -> Optional.empty());
         assertTrue(getMetaData().getSchemaMetaData().getConfiguredSchemaMetaData().get("t_order").getIndexes().containsKey("t_order_index"));
     }
     
     @Test
-    public void refreshMySQLCreateIndexMetaDataIfIndexIsNull() throws SQLException {
+    public void refreshMetaDataIfIndexIsNullForMySQL() throws SQLException {
         refreshMetaDataIfIndexIsNull(new MySQLCreateIndexStatement());
     }
     
     @Test
-    public void refreshOracleCreateIndexMetaDataIfIndexIsNull() throws SQLException {
+    public void refreshMetaDataIfIndexIsNullForOracle() throws SQLException {
         refreshMetaDataIfIndexIsNull(new OracleCreateIndexStatement());
     }
     
     @Test
-    public void refreshPostgreSQLCreateIndexMetaDataIfIndexIsNull() throws SQLException {
+    public void refreshMetaDataIfIndexIsNullForPostgreSQL() throws SQLException {
         refreshMetaDataIfIndexIsNull(new PostgreSQLCreateIndexStatement());
     }
     
     @Test
-    public void refreshSQLServerCreateIndexMetaDataIfIndexIsNull() throws SQLException {
+    public void refreshMetaDataIfIndexIsNullForSQLServer() throws SQLException {
         refreshMetaDataIfIndexIsNull(new SQLServerCreateIndexStatement());
     }
     
     private void refreshMetaDataIfIndexIsNull(final CreateIndexStatement createIndexStatement) throws SQLException {
         MetaDataRefreshStrategy<CreateIndexStatement> metaDataRefreshStrategy = new CreateIndexStatementMetaDataRefreshStrategy();
         createIndexStatement.setTable(new SimpleTableSegment(new TableNameSegment(1, 3, new IdentifierValue("t_order"))));
-        metaDataRefreshStrategy.refreshMetaData(getMetaData(), mock(DatabaseType.class), Collections.emptyMap(), createIndexStatement, tableName -> Optional.empty());
+        metaDataRefreshStrategy.refreshMetaData(getMetaData(), mock(DatabaseType.class), Collections.emptyList(), createIndexStatement, tableName -> Optional.empty());
         assertFalse(getMetaData().getSchemaMetaData().getConfiguredSchemaMetaData().get("t_order").getIndexes().containsKey("t_order_index"));
     }
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-common/src/test/java/org/apache/shardingsphere/infra/metadata/refresh/impl/CreateTableStatementMetaDataRefreshStrategyTest.java b/shardingsphere-infra/shardingsphere-infra-common/src/test/java/org/apache/shardingsphere/infra/metadata/refresh/impl/CreateTableStatementMetaDataRefreshStrategyTest.java
index 4f5a931..894b1fa 100644
--- a/shardingsphere-infra/shardingsphere-infra-common/src/test/java/org/apache/shardingsphere/infra/metadata/refresh/impl/CreateTableStatementMetaDataRefreshStrategyTest.java
+++ b/shardingsphere-infra/shardingsphere-infra-common/src/test/java/org/apache/shardingsphere/infra/metadata/refresh/impl/CreateTableStatementMetaDataRefreshStrategyTest.java
@@ -35,51 +35,43 @@ import org.apache.shardingsphere.sql.parser.sql.dialect.statement.sql92.ddl.SQL9
 import org.apache.shardingsphere.sql.parser.sql.dialect.statement.sqlserver.ddl.SQLServerCreateTableStatement;
 import org.junit.Test;
 
-import javax.sql.DataSource;
-import java.sql.Connection;
-import java.sql.DatabaseMetaData;
-import java.sql.ResultSet;
 import java.sql.SQLException;
-import java.sql.Statement;
 import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.Map;
 import java.util.Optional;
 
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
 
 public final class CreateTableStatementMetaDataRefreshStrategyTest extends AbstractMetaDataRefreshStrategyTest {
     
     @Test
-    public void refreshMySQLCreateTableMetaData() throws SQLException {
+    public void refreshMetaDataForMySQL() throws SQLException {
         MySQLCreateTableStatement createTableStatement = new MySQLCreateTableStatement();
         createTableStatement.setNotExisted(false);
         refreshMetaData(createTableStatement);
     }
 
     @Test
-    public void refreshOracleCreateTableMetaData() throws SQLException {
+    public void refreshMetaDataForOracle() throws SQLException {
         OracleCreateTableStatement createTableStatement = new OracleCreateTableStatement();
         refreshMetaData(createTableStatement);
     }
 
     @Test
-    public void refreshPostgreSQLCreateTableMetaData() throws SQLException {
+    public void refreshMetaDataForPostgreSQL() throws SQLException {
         PostgreSQLCreateTableStatement createTableStatement = new PostgreSQLCreateTableStatement();
         createTableStatement.setNotExisted(false);
         refreshMetaData(createTableStatement);
     }
 
     @Test
-    public void refreshSQL92CreateTableMetaData() throws SQLException {
+    public void refreshMetaDataForSQL92() throws SQLException {
         SQL92CreateTableStatement createTableStatement = new SQL92CreateTableStatement();
         refreshMetaData(createTableStatement);
     }
 
     @Test
-    public void refreshSQLServerCreateTableMetaData() throws SQLException {
+    public void refreshMetaDataForSQLServer() throws SQLException {
         SQLServerCreateTableStatement createTableStatement = new SQLServerCreateTableStatement();
         refreshMetaData(createTableStatement);
     }
@@ -87,74 +79,48 @@ public final class CreateTableStatementMetaDataRefreshStrategyTest extends Abstr
     private void refreshMetaData(final CreateTableStatement createTableStatement) throws SQLException {
         createTableStatement.setTable(new SimpleTableSegment(new TableNameSegment(1, 3, new IdentifierValue("t_order_0"))));
         MetaDataRefreshStrategy<CreateTableStatement> metaDataRefreshStrategy = new CreateTableStatementMetaDataRefreshStrategy();
-        metaDataRefreshStrategy.refreshMetaData(getMetaData(), mock(DatabaseType.class), Collections.emptyMap(), createTableStatement, tableName -> Optional.of(new PhysicalTableMetaData(
+        metaDataRefreshStrategy.refreshMetaData(getMetaData(), mock(DatabaseType.class), Collections.emptyList(), createTableStatement, tableName -> Optional.of(new PhysicalTableMetaData(
                 Collections.singletonList(new PhysicalColumnMetaData("order_id", 1, "String", true, false, false)),
                 Collections.singletonList(new PhysicalIndexMetaData("index")))));
         assertTrue(getMetaData().getSchemaMetaData().getConfiguredSchemaMetaData().containsTable("t_order_0"));
     }
     
     @Test
-    public void assertRefreshMySQLCreateTableMetaDataWithUnConfigured() throws SQLException {
+    public void refreshMetaDataWithUnConfiguredForMySQL() throws SQLException {
         MySQLCreateTableStatement createTableStatement = new MySQLCreateTableStatement();
         createTableStatement.setNotExisted(false);
-        assertRefreshMetaDataWithUnConfigured(createTableStatement);
+        refreshMetaDataWithUnConfigured(createTableStatement);
     }
 
     @Test
-    public void assertRefreshOracleCreateTableMetaDataWithUnConfigured() throws SQLException {
+    public void refreshMetaDataWithUnConfiguredForOracle() throws SQLException {
         OracleCreateTableStatement createTableStatement = new OracleCreateTableStatement();
-        assertRefreshMetaDataWithUnConfigured(createTableStatement);
+        refreshMetaDataWithUnConfigured(createTableStatement);
     }
 
     @Test
-    public void assertRefreshPostgreSQLCreateTableMetaDataWithUnConfigured() throws SQLException {
+    public void refreshMetaDataWithUnConfiguredForPostgreSQL() throws SQLException {
         PostgreSQLCreateTableStatement createTableStatement = new PostgreSQLCreateTableStatement();
         createTableStatement.setNotExisted(false);
-        assertRefreshMetaDataWithUnConfigured(createTableStatement);
+        refreshMetaDataWithUnConfigured(createTableStatement);
     }
 
     @Test
-    public void assertRefreshSQL92CreateTableMetaDataWithUnConfigured() throws SQLException {
+    public void refreshMetaDataWithUnConfiguredForSQL92() throws SQLException {
         SQL92CreateTableStatement createTableStatement = new SQL92CreateTableStatement();
-        assertRefreshMetaDataWithUnConfigured(createTableStatement);
+        refreshMetaDataWithUnConfigured(createTableStatement);
     }
 
     @Test
-    public void assertRefreshSQLServerCreateTableMetaDataWithUnConfigured() throws SQLException {
+    public void refreshMetaDataWithUnConfiguredForSQLServer() throws SQLException {
         SQLServerCreateTableStatement createTableStatement = new SQLServerCreateTableStatement();
-        assertRefreshMetaDataWithUnConfigured(createTableStatement);
+        refreshMetaDataWithUnConfigured(createTableStatement);
     }
 
-    private void assertRefreshMetaDataWithUnConfigured(final CreateTableStatement createTableStatement) throws SQLException {
+    private void refreshMetaDataWithUnConfigured(final CreateTableStatement createTableStatement) throws SQLException {
         createTableStatement.setTable(new SimpleTableSegment(new TableNameSegment(1, 3, new IdentifierValue("t_order_item_0"))));
-        Map<String, DataSource> dataSourceSourceMap = new LinkedHashMap<>(1, 1);
-        dataSourceSourceMap.put("t_order_item", initDataSource());
         MetaDataRefreshStrategy<CreateTableStatement> metaDataRefreshStrategy = new CreateTableStatementMetaDataRefreshStrategy();
-        metaDataRefreshStrategy.refreshMetaData(getMetaData(), new MySQLDatabaseType(), dataSourceSourceMap, createTableStatement, tableName -> Optional.empty());
+        metaDataRefreshStrategy.refreshMetaData(getMetaData(), new MySQLDatabaseType(), Collections.singletonList("t_order_item"), createTableStatement, tableName -> Optional.empty());
         assertTrue(getMetaData().getSchemaMetaData().getUnconfiguredSchemaMetaDataMap().get("t_order_item").contains("t_order_item_0"));
     }
-    
-    private DataSource initDataSource() throws SQLException {
-        final String catalog = "catalog";
-        final String table = "t_order_item_0";
-        DataSource result = mock(DataSource.class);
-        Connection connection = mock(Connection.class);
-        when(result.getConnection()).thenReturn(connection);
-        when(connection.getCatalog()).thenReturn(catalog);
-        when(connection.getSchema()).thenReturn("");
-        DatabaseMetaData databaseMetaData = mock(DatabaseMetaData.class);
-        when(connection.getMetaData()).thenReturn(databaseMetaData);
-        Statement statement = mock(Statement.class);
-        when(connection.createStatement()).thenReturn(statement);
-        ResultSet columnMetaDataResultSet = mock(ResultSet.class);
-        ResultSet primaryKeyResultSet = mock(ResultSet.class);
-        ResultSet tableResultSet = mock(ResultSet.class);
-        ResultSet indexMetaDataResultSet = mock(ResultSet.class);
-        when(databaseMetaData.getColumns(catalog, "", table, "%")).thenReturn(columnMetaDataResultSet);
-        when(databaseMetaData.getPrimaryKeys(catalog, "", table)).thenReturn(primaryKeyResultSet);
-        when(databaseMetaData.getTables(catalog, "", table, null)).thenReturn(tableResultSet);
-        when(databaseMetaData.getIndexInfo(catalog, "", table, false, false)).thenReturn(indexMetaDataResultSet);
-        when(tableResultSet.next()).thenReturn(true);
-        return result;
-    }
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-common/src/test/java/org/apache/shardingsphere/infra/metadata/refresh/impl/DropIndexStatementMetaDataRefreshStrategyTest.java b/shardingsphere-infra/shardingsphere-infra-common/src/test/java/org/apache/shardingsphere/infra/metadata/refresh/impl/DropIndexStatementMetaDataRefreshStrategyTest.java
index ad4019a..f304397 100644
--- a/shardingsphere-infra/shardingsphere-infra-common/src/test/java/org/apache/shardingsphere/infra/metadata/refresh/impl/DropIndexStatementMetaDataRefreshStrategyTest.java
+++ b/shardingsphere-infra/shardingsphere-infra-common/src/test/java/org/apache/shardingsphere/infra/metadata/refresh/impl/DropIndexStatementMetaDataRefreshStrategyTest.java
@@ -57,7 +57,7 @@ public final class DropIndexStatementMetaDataRefreshStrategyTest extends Abstrac
     private void refreshMetaData(final DropIndexStatement dropIndexStatement) throws SQLException {
         dropIndexStatement.getIndexes().add(new IndexSegment(1, 2, new IdentifierValue("index")));
         MetaDataRefreshStrategy<DropIndexStatement> metaDataRefreshStrategy = new DropIndexStatementMetaDataRefreshStrategy();
-        metaDataRefreshStrategy.refreshMetaData(getMetaData(), mock(DatabaseType.class), Collections.emptyMap(), dropIndexStatement, tableName -> Optional.empty());
+        metaDataRefreshStrategy.refreshMetaData(getMetaData(), mock(DatabaseType.class), Collections.emptyList(), dropIndexStatement, tableName -> Optional.empty());
         assertFalse(getMetaData().getSchemaMetaData().getConfiguredSchemaMetaData().get("t_order").getIndexes().containsKey("index"));
     }
     
@@ -83,7 +83,7 @@ public final class DropIndexStatementMetaDataRefreshStrategyTest extends Abstrac
         actualIndex.put("t_order_index", new PhysicalIndexMetaData("t_order_index"));
         actualIndex.put("order_id_index", new PhysicalIndexMetaData("order_id_index"));
         MetaDataRefreshStrategy<DropIndexStatement> metaDataRefreshStrategy = new DropIndexStatementMetaDataRefreshStrategy();
-        metaDataRefreshStrategy.refreshMetaData(getMetaData(), mock(DatabaseType.class), Collections.emptyMap(), dropIndexStatement, tableName -> Optional.empty());
+        metaDataRefreshStrategy.refreshMetaData(getMetaData(), mock(DatabaseType.class), Collections.emptyList(), dropIndexStatement, tableName -> Optional.empty());
         assertFalse(getMetaData().getSchemaMetaData().getConfiguredSchemaMetaData().get("t_order").getIndexes().containsKey("index"));
         assertFalse(getMetaData().getSchemaMetaData().getConfiguredSchemaMetaData().get("t_order").getIndexes().containsKey("t_order_index"));
         assertFalse(getMetaData().getSchemaMetaData().getConfiguredSchemaMetaData().get("t_order").getIndexes().containsKey("order_id_index"));
diff --git a/shardingsphere-infra/shardingsphere-infra-common/src/test/java/org/apache/shardingsphere/infra/metadata/refresh/impl/DropTableStatementMetaDataRefreshStrategyTest.java b/shardingsphere-infra/shardingsphere-infra-common/src/test/java/org/apache/shardingsphere/infra/metadata/refresh/impl/DropTableStatementMetaDataRefreshStrategyTest.java
index f5936ad..cdb0014 100644
--- a/shardingsphere-infra/shardingsphere-infra-common/src/test/java/org/apache/shardingsphere/infra/metadata/refresh/impl/DropTableStatementMetaDataRefreshStrategyTest.java
+++ b/shardingsphere-infra/shardingsphere-infra-common/src/test/java/org/apache/shardingsphere/infra/metadata/refresh/impl/DropTableStatementMetaDataRefreshStrategyTest.java
@@ -41,34 +41,66 @@ import static org.mockito.Mockito.mock;
 public final class DropTableStatementMetaDataRefreshStrategyTest extends AbstractMetaDataRefreshStrategyTest {
     
     @Test
-    public void refreshMySQLDropTableMetaData() throws SQLException {
+    public void refreshDropTableMetaDataForMySQL() throws SQLException {
         refreshMetaData(new MySQLDropTableStatement());   
     }
     
     @Test
-    public void refreshOracleDropTableMetaData() throws SQLException {
+    public void refreshDropTableMetaDataForOracle() throws SQLException {
         refreshMetaData(new OracleDropTableStatement());
     }
     
     @Test
-    public void refreshPostgreSQLDropTableMetaData() throws SQLException {
+    public void refreshDropTableMetaDataForPostgreSQL() throws SQLException {
         refreshMetaData(new PostgreSQLDropTableStatement());
     }
     
     @Test
-    public void refreshSQL92DropTableMetaData() throws SQLException {
+    public void refreshDropTableMetaDataForSQL92() throws SQLException {
         refreshMetaData(new SQL92DropTableStatement());
     }
     
     @Test
-    public void refreshSQLServerDropTableMetaData() throws SQLException {
+    public void refreshDropTableMetaDataForSQLServer() throws SQLException {
         refreshMetaData(new SQLServerDropTableStatement());
     }
     
     private void refreshMetaData(final DropTableStatement dropTableStatement) throws SQLException {
         MetaDataRefreshStrategy<DropTableStatement> metaDataRefreshStrategy = new DropTableStatementMetaDataRefreshStrategy();
         dropTableStatement.getTables().add(new SimpleTableSegment(new TableNameSegment(1, 3, new IdentifierValue("t_order"))));
-        metaDataRefreshStrategy.refreshMetaData(getMetaData(), mock(DatabaseType.class), Collections.emptyMap(), dropTableStatement, tableName -> Optional.empty());
+        metaDataRefreshStrategy.refreshMetaData(getMetaData(), mock(DatabaseType.class), Collections.emptyList(), dropTableStatement, tableName -> Optional.empty());
         assertFalse(getMetaData().getSchemaMetaData().getConfiguredSchemaMetaData().containsTable("t_order"));
     }
+    
+    @Test
+    public void refreshMetaDataWithUnConfiguredForMySQL() throws SQLException {
+        refreshMetaDataWithUnConfigured(new MySQLDropTableStatement());
+    }
+    
+    @Test
+    public void refreshMetaDataWithUnConfiguredForOracle() throws SQLException {
+        refreshMetaDataWithUnConfigured(new OracleDropTableStatement());
+    }
+    
+    @Test
+    public void refreshMetaDataWithUnConfiguredForPostgreSQL() throws SQLException {
+        refreshMetaDataWithUnConfigured(new PostgreSQLDropTableStatement());
+    }
+    
+    @Test
+    public void refreshMetaDataWithUnConfiguredForSQL92() throws SQLException {
+        refreshMetaDataWithUnConfigured(new SQL92DropTableStatement());
+    }
+    
+    @Test
+    public void refreshMetaDataWithUnConfiguredForSQLServer() throws SQLException {
+        refreshMetaDataWithUnConfigured(new SQLServerDropTableStatement());
+    }
+    
+    private void refreshMetaDataWithUnConfigured(final DropTableStatement dropTableStatement) throws SQLException {
+        MetaDataRefreshStrategy<DropTableStatement> metaDataRefreshStrategy = new DropTableStatementMetaDataRefreshStrategy();
+        dropTableStatement.getTables().add(new SimpleTableSegment(new TableNameSegment(1, 3, new IdentifierValue("t_order_item"))));
+        metaDataRefreshStrategy.refreshMetaData(getMetaData(), mock(DatabaseType.class), Collections.singletonList("t_order_item"), dropTableStatement, tableName -> Optional.empty());
+        assertFalse(getMetaData().getSchemaMetaData().getUnconfiguredSchemaMetaDataMap().get("t_order_item").contains("t_order_item"));
+    }
 }
diff --git a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/executor/AbstractStatementExecutor.java b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/executor/AbstractStatementExecutor.java
index d6a773e..bb66153 100644
--- a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/executor/AbstractStatementExecutor.java
+++ b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/executor/AbstractStatementExecutor.java
@@ -27,11 +27,13 @@ import org.apache.shardingsphere.infra.executor.sql.QueryResult;
 import org.apache.shardingsphere.infra.executor.sql.resourced.jdbc.StatementExecuteUnit;
 import org.apache.shardingsphere.infra.executor.sql.resourced.jdbc.executor.SQLExecutor;
 import org.apache.shardingsphere.infra.executor.sql.resourced.jdbc.executor.SQLExecutorCallback;
-import org.apache.shardingsphere.infra.metadata.refresh.MetaDataRefreshStrategy;
-import org.apache.shardingsphere.infra.metadata.refresh.MetaDataRefreshStrategyFactory;
 import org.apache.shardingsphere.infra.metadata.model.logic.LogicSchemaMetaData;
 import org.apache.shardingsphere.infra.metadata.model.logic.LogicSchemaMetaDataLoader;
 import org.apache.shardingsphere.infra.metadata.model.logic.spi.LogicMetaDataNotifier;
+import org.apache.shardingsphere.infra.metadata.refresh.MetaDataRefreshStrategy;
+import org.apache.shardingsphere.infra.metadata.refresh.MetaDataRefreshStrategyFactory;
+import org.apache.shardingsphere.infra.route.context.RouteMapper;
+import org.apache.shardingsphere.infra.route.context.RouteUnit;
 import org.apache.shardingsphere.infra.rule.DataNodeRoutedRule;
 import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
 import org.apache.shardingsphere.infra.schema.ShardingSphereSchema;
@@ -46,6 +48,7 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import java.util.stream.Collectors;
 
 /**
  * Abstract statement executor.
@@ -73,23 +76,24 @@ public abstract class AbstractStatementExecutor {
     }
     
     @SuppressWarnings({"unchecked", "rawtypes"})
-    protected final void refreshTableMetaData(final ShardingSphereSchema schema, final SQLStatement sqlStatement) throws SQLException {
+    protected final void refreshTableMetaData(final ShardingSphereSchema schema, final SQLStatement sqlStatement, final Collection<RouteUnit> routeUnits) throws SQLException {
         if (null == sqlStatement) {
             return;
         }
         Optional<MetaDataRefreshStrategy> refreshStrategy = MetaDataRefreshStrategyFactory.newInstance(sqlStatement);
         if (refreshStrategy.isPresent()) {
             LogicSchemaMetaDataLoader metaDataLoader = new LogicSchemaMetaDataLoader(schema.getRules());
-            refreshStrategy.get().refreshMetaData(schema.getMetaData(), schemaContexts.getDatabaseType(), dataSourceMap, sqlStatement, 
-                tableName -> metaDataLoader.load(schemaContexts.getDatabaseType(), dataSourceMap, tableName, schemaContexts.getProps()));
+            Collection<String> routeDataSourceNames = routeUnits.stream().map(RouteUnit::getDataSourceMapper).map(RouteMapper::getLogicName).collect(Collectors.toList());
+            refreshStrategy.get().refreshMetaData(schema.getMetaData(), schemaContexts.getDatabaseType(), routeDataSourceNames, 
+                    sqlStatement, tableName -> metaDataLoader.load(schemaContexts.getDatabaseType(), dataSourceMap, tableName, schemaContexts.getProps()));
             notifyPersistLogicMetaData(DefaultSchema.LOGIC_NAME, schema.getMetaData().getSchemaMetaData());
         }
     }
     
     protected boolean executeAndRefreshMetaData(final Collection<InputGroup<StatementExecuteUnit>> inputGroups, final SQLStatement sqlStatement,
-                                                final SQLExecutorCallback<Boolean> sqlExecutorCallback) throws SQLException {
+                                                final Collection<RouteUnit> routeUnits, final SQLExecutorCallback<Boolean> sqlExecutorCallback) throws SQLException {
         List<Boolean> result = sqlExecutor.execute(inputGroups, sqlExecutorCallback);
-        refreshTableMetaData(schemaContexts.getDefaultSchema(), sqlStatement);
+        refreshTableMetaData(schemaContexts.getDefaultSchema(), sqlStatement, routeUnits);
         return null != result && !result.isEmpty() && null != result.get(0) && result.get(0);
     }
     
@@ -102,10 +106,11 @@ public abstract class AbstractStatementExecutor {
      *
      * @param inputGroups input groups
      * @param sqlStatement SQL statement
+     * @param routeUnits route units
      * @return return true if is DQL, false if is DML
      * @throws SQLException SQL exception
      */
-    public abstract boolean execute(Collection<InputGroup<StatementExecuteUnit>> inputGroups, SQLStatement sqlStatement) throws SQLException;
+    public abstract boolean execute(Collection<InputGroup<StatementExecuteUnit>> inputGroups, SQLStatement sqlStatement, Collection<RouteUnit> routeUnits) throws SQLException;
     
     /**
      * Execute query.
@@ -121,8 +126,9 @@ public abstract class AbstractStatementExecutor {
      *
      * @param inputGroups input groups
      * @param sqlStatementContext SQL statement context
+     * @param routeUnits route units
      * @return effected records count
      * @throws SQLException SQL exception
      */
-    public abstract int executeUpdate(Collection<InputGroup<StatementExecuteUnit>> inputGroups, SQLStatementContext<?> sqlStatementContext) throws SQLException;
+    public abstract int executeUpdate(Collection<InputGroup<StatementExecuteUnit>> inputGroups, SQLStatementContext<?> sqlStatementContext, Collection<RouteUnit> routeUnits) throws SQLException;
 }
diff --git a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/executor/PreparedStatementExecutor.java b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/executor/PreparedStatementExecutor.java
index 03a407e..85504c8 100644
--- a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/executor/PreparedStatementExecutor.java
+++ b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/executor/PreparedStatementExecutor.java
@@ -29,6 +29,7 @@ import org.apache.shardingsphere.infra.executor.sql.resourced.jdbc.executor.SQLE
 import org.apache.shardingsphere.infra.executor.sql.resourced.jdbc.executor.impl.DefaultSQLExecutorCallback;
 import org.apache.shardingsphere.infra.executor.sql.resourced.jdbc.queryresult.MemoryQueryResult;
 import org.apache.shardingsphere.infra.executor.sql.resourced.jdbc.queryresult.StreamQueryResult;
+import org.apache.shardingsphere.infra.route.context.RouteUnit;
 import org.apache.shardingsphere.infra.rule.DataNodeRoutedRule;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
 
@@ -75,11 +76,12 @@ public final class PreparedStatementExecutor extends AbstractStatementExecutor {
     }
     
     @Override
-    public int executeUpdate(final Collection<InputGroup<StatementExecuteUnit>> inputGroups, final SQLStatementContext<?> sqlStatementContext) throws SQLException {
+    public int executeUpdate(final Collection<InputGroup<StatementExecuteUnit>> inputGroups, 
+                             final SQLStatementContext<?> sqlStatementContext, final Collection<RouteUnit> routeUnits) throws SQLException {
         boolean isExceptionThrown = ExecutorExceptionHandler.isExceptionThrown();
         SQLExecutorCallback<Integer> sqlExecutorCallback = createDefaultSQLExecutorCallbackWithInteger(isExceptionThrown);
         List<Integer> results = getSqlExecutor().execute(inputGroups, sqlExecutorCallback);
-        refreshTableMetaData(getSchemaContexts().getDefaultSchema(), sqlStatementContext.getSqlStatement());
+        refreshTableMetaData(getSchemaContexts().getDefaultSchema(), sqlStatementContext.getSqlStatement(), routeUnits);
         return isNeedAccumulate(
                 getSchemaContexts().getDefaultSchema().getRules().stream().filter(rule -> rule instanceof DataNodeRoutedRule).collect(Collectors.toList()), sqlStatementContext)
                 ? accumulate(results) : results.get(0);
@@ -96,10 +98,10 @@ public final class PreparedStatementExecutor extends AbstractStatementExecutor {
     }
     
     @Override
-    public boolean execute(final Collection<InputGroup<StatementExecuteUnit>> inputGroups, final SQLStatement sqlStatement) throws SQLException {
+    public boolean execute(final Collection<InputGroup<StatementExecuteUnit>> inputGroups, final SQLStatement sqlStatement, final Collection<RouteUnit> routeUnits) throws SQLException {
         boolean isExceptionThrown = ExecutorExceptionHandler.isExceptionThrown();
         SQLExecutorCallback<Boolean> sqlExecutorCallback = createDefaultSQLExecutorCallbackWithBoolean(isExceptionThrown);
-        return executeAndRefreshMetaData(inputGroups, sqlStatement, sqlExecutorCallback);
+        return executeAndRefreshMetaData(inputGroups, sqlStatement, routeUnits, sqlExecutorCallback);
     }
     
     private DefaultSQLExecutorCallback<Boolean> createDefaultSQLExecutorCallbackWithBoolean(final boolean isExceptionThrown) {
diff --git a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/executor/StatementExecutor.java b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/executor/StatementExecutor.java
index 17d1e28..3c73f9d 100644
--- a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/executor/StatementExecutor.java
+++ b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/executor/StatementExecutor.java
@@ -29,6 +29,7 @@ import org.apache.shardingsphere.infra.executor.sql.resourced.jdbc.executor.SQLE
 import org.apache.shardingsphere.infra.executor.sql.resourced.jdbc.executor.impl.DefaultSQLExecutorCallback;
 import org.apache.shardingsphere.infra.executor.sql.resourced.jdbc.queryresult.MemoryQueryResult;
 import org.apache.shardingsphere.infra.executor.sql.resourced.jdbc.queryresult.StreamQueryResult;
+import org.apache.shardingsphere.infra.route.context.RouteUnit;
 import org.apache.shardingsphere.infra.rule.DataNodeRoutedRule;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
 
@@ -69,8 +70,9 @@ public final class StatementExecutor extends AbstractStatementExecutor {
     }
     
     @Override
-    public int executeUpdate(final Collection<InputGroup<StatementExecuteUnit>> inputGroups, final SQLStatementContext<?> sqlStatementContext) throws SQLException {
-        return executeUpdate(inputGroups, Statement::executeUpdate, sqlStatementContext);
+    public int executeUpdate(final Collection<InputGroup<StatementExecuteUnit>> inputGroups, 
+                             final SQLStatementContext<?> sqlStatementContext, final Collection<RouteUnit> routeUnits) throws SQLException {
+        return executeUpdate(inputGroups, Statement::executeUpdate, sqlStatementContext, routeUnits);
     }
     
     /**
@@ -78,12 +80,14 @@ public final class StatementExecutor extends AbstractStatementExecutor {
      * 
      * @param inputGroups input groups
      * @param sqlStatementContext SQL statement context
+     * @param routeUnits route units
      * @param autoGeneratedKeys auto generated keys' flag
      * @return effected records count
      * @throws SQLException SQL exception
      */
-    public int executeUpdate(final Collection<InputGroup<StatementExecuteUnit>> inputGroups, final SQLStatementContext<?> sqlStatementContext, final int autoGeneratedKeys) throws SQLException {
-        return executeUpdate(inputGroups, (statement, sql) -> statement.executeUpdate(sql, autoGeneratedKeys), sqlStatementContext);
+    public int executeUpdate(final Collection<InputGroup<StatementExecuteUnit>> inputGroups, final SQLStatementContext<?> sqlStatementContext,
+                             final Collection<RouteUnit> routeUnits, final int autoGeneratedKeys) throws SQLException {
+        return executeUpdate(inputGroups, (statement, sql) -> statement.executeUpdate(sql, autoGeneratedKeys), sqlStatementContext, routeUnits);
     }
     
     /**
@@ -91,12 +95,14 @@ public final class StatementExecutor extends AbstractStatementExecutor {
      *
      * @param inputGroups input groups
      * @param sqlStatementContext SQL statement context
+     * @param routeUnits route units
      * @param columnIndexes column indexes
      * @return effected records count
      * @throws SQLException SQL exception
      */
-    public int executeUpdate(final Collection<InputGroup<StatementExecuteUnit>> inputGroups, final SQLStatementContext<?> sqlStatementContext, final int[] columnIndexes) throws SQLException {
-        return executeUpdate(inputGroups, (statement, sql) -> statement.executeUpdate(sql, columnIndexes), sqlStatementContext);
+    public int executeUpdate(final Collection<InputGroup<StatementExecuteUnit>> inputGroups, final SQLStatementContext<?> sqlStatementContext,
+                             final Collection<RouteUnit> routeUnits, final int[] columnIndexes) throws SQLException {
+        return executeUpdate(inputGroups, (statement, sql) -> statement.executeUpdate(sql, columnIndexes), sqlStatementContext, routeUnits);
     }
     
     /**
@@ -104,16 +110,19 @@ public final class StatementExecutor extends AbstractStatementExecutor {
      *
      * @param inputGroups input groups
      * @param sqlStatementContext SQL statement context
+     * @param routeUnits route units
      * @param columnNames column names
      * @return effected records count
      * @throws SQLException SQL exception
      */
-    public int executeUpdate(final Collection<InputGroup<StatementExecuteUnit>> inputGroups, final SQLStatementContext<?> sqlStatementContext, final String[] columnNames) throws SQLException {
-        return executeUpdate(inputGroups, (statement, sql) -> statement.executeUpdate(sql, columnNames), sqlStatementContext);
+    public int executeUpdate(final Collection<InputGroup<StatementExecuteUnit>> inputGroups, final SQLStatementContext<?> sqlStatementContext,
+                             final Collection<RouteUnit> routeUnits, final String[] columnNames) throws SQLException {
+        return executeUpdate(inputGroups, (statement, sql) -> statement.executeUpdate(sql, columnNames), sqlStatementContext, routeUnits);
     }
     
     @SuppressWarnings({"unchecked", "rawtypes"})
-    private int executeUpdate(final Collection<InputGroup<StatementExecuteUnit>> inputGroups, final Updater updater, final SQLStatementContext<?> sqlStatementContext) throws SQLException {
+    private int executeUpdate(final Collection<InputGroup<StatementExecuteUnit>> inputGroups, final Updater updater, 
+                              final SQLStatementContext<?> sqlStatementContext, final Collection<RouteUnit> routeUnits) throws SQLException {
         boolean isExceptionThrown = ExecutorExceptionHandler.isExceptionThrown();
         SQLExecutorCallback sqlExecutorCallback = new DefaultSQLExecutorCallback<Integer>(getSchemaContexts().getDatabaseType(), isExceptionThrown) {
             
@@ -123,7 +132,7 @@ public final class StatementExecutor extends AbstractStatementExecutor {
             }
         };
         List<Integer> results = getSqlExecutor().execute(inputGroups, sqlExecutorCallback);
-        refreshTableMetaData(getSchemaContexts().getDefaultSchema(), sqlStatementContext.getSqlStatement());
+        refreshTableMetaData(getSchemaContexts().getDefaultSchema(), sqlStatementContext.getSqlStatement(), routeUnits);
         if (isNeedAccumulate(
                 getSchemaContexts().getDefaultSchema().getRules().stream().filter(rule -> rule instanceof DataNodeRoutedRule).collect(Collectors.toList()), sqlStatementContext)) {
             return accumulate(results);
@@ -132,8 +141,8 @@ public final class StatementExecutor extends AbstractStatementExecutor {
     }
     
     @Override
-    public boolean execute(final Collection<InputGroup<StatementExecuteUnit>> inputGroups, final SQLStatement sqlStatement) throws SQLException {
-        return execute(inputGroups, Statement::execute, sqlStatement);
+    public boolean execute(final Collection<InputGroup<StatementExecuteUnit>> inputGroups, final SQLStatement sqlStatement, final Collection<RouteUnit> routeUnits) throws SQLException {
+        return execute(inputGroups, Statement::execute, sqlStatement, routeUnits);
     }
     
     /**
@@ -141,12 +150,14 @@ public final class StatementExecutor extends AbstractStatementExecutor {
      *
      * @param inputGroups input groups
      * @param sqlStatement SQL statement
+     * @param routeUnits route units
      * @param autoGeneratedKeys auto generated keys' flag
      * @return return true if is DQL, false if is DML
      * @throws SQLException SQL exception
      */
-    public boolean execute(final Collection<InputGroup<StatementExecuteUnit>> inputGroups, final SQLStatement sqlStatement, final int autoGeneratedKeys) throws SQLException {
-        return execute(inputGroups, (statement, sql) -> statement.execute(sql, autoGeneratedKeys), sqlStatement);
+    public boolean execute(final Collection<InputGroup<StatementExecuteUnit>> inputGroups, final SQLStatement sqlStatement,
+                           final Collection<RouteUnit> routeUnits, final int autoGeneratedKeys) throws SQLException {
+        return execute(inputGroups, (statement, sql) -> statement.execute(sql, autoGeneratedKeys), sqlStatement, routeUnits);
     }
     
     /**
@@ -154,12 +165,14 @@ public final class StatementExecutor extends AbstractStatementExecutor {
      *
      * @param inputGroups input groups
      * @param sqlStatement SQL statement
+     * @param routeUnits route units
      * @param columnIndexes column indexes
      * @return return true if is DQL, false if is DML
      * @throws SQLException SQL exception
      */
-    public boolean execute(final Collection<InputGroup<StatementExecuteUnit>> inputGroups, final SQLStatement sqlStatement, final int[] columnIndexes) throws SQLException {
-        return execute(inputGroups, (statement, sql) -> statement.execute(sql, columnIndexes), sqlStatement);
+    public boolean execute(final Collection<InputGroup<StatementExecuteUnit>> inputGroups, final SQLStatement sqlStatement,
+                           final Collection<RouteUnit> routeUnits, final int[] columnIndexes) throws SQLException {
+        return execute(inputGroups, (statement, sql) -> statement.execute(sql, columnIndexes), sqlStatement, routeUnits);
     }
     
     /**
@@ -167,16 +180,19 @@ public final class StatementExecutor extends AbstractStatementExecutor {
      *
      * @param inputGroups input groups
      * @param sqlStatement SQL statement
+     * @param routeUnits route units
      * @param columnNames column names
      * @return return true if is DQL, false if is DML
      * @throws SQLException SQL exception
      */
-    public boolean execute(final Collection<InputGroup<StatementExecuteUnit>> inputGroups, final SQLStatement sqlStatement, final String[] columnNames) throws SQLException {
-        return execute(inputGroups, (statement, sql) -> statement.execute(sql, columnNames), sqlStatement);
+    public boolean execute(final Collection<InputGroup<StatementExecuteUnit>> inputGroups, final SQLStatement sqlStatement,
+                           final Collection<RouteUnit> routeUnits, final String[] columnNames) throws SQLException {
+        return execute(inputGroups, (statement, sql) -> statement.execute(sql, columnNames), sqlStatement, routeUnits);
     }
     
     @SuppressWarnings({"unchecked", "rawtypes"})
-    private boolean execute(final Collection<InputGroup<StatementExecuteUnit>> inputGroups, final Executor executor, final SQLStatement sqlStatement) throws SQLException {
+    private boolean execute(final Collection<InputGroup<StatementExecuteUnit>> inputGroups, final Executor executor, 
+                            final SQLStatement sqlStatement, final Collection<RouteUnit> routeUnits) throws SQLException {
         boolean isExceptionThrown = ExecutorExceptionHandler.isExceptionThrown();
         SQLExecutorCallback sqlExecutorCallback = new DefaultSQLExecutorCallback<Boolean>(getSchemaContexts().getDatabaseType(), isExceptionThrown) {
             
@@ -185,7 +201,7 @@ public final class StatementExecutor extends AbstractStatementExecutor {
                 return executor.execute(statement, sql);
             }
         };
-        return executeAndRefreshMetaData(inputGroups, sqlStatement, sqlExecutorCallback);
+        return executeAndRefreshMetaData(inputGroups, sqlStatement, routeUnits, sqlExecutorCallback);
     }
     
     private interface Updater {
diff --git a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSpherePreparedStatement.java b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSpherePreparedStatement.java
index 79ac648..4838d8c 100644
--- a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSpherePreparedStatement.java
+++ b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSpherePreparedStatement.java
@@ -182,7 +182,7 @@ public final class ShardingSpherePreparedStatement extends AbstractPreparedState
                 Collection<InputGroup<StatementExecuteUnit>> inputGroups = getInputGroups();
                 cacheStatements(inputGroups);
                 reply();
-                return preparedStatementExecutor.executeUpdate(inputGroups, executionContext.getSqlStatementContext());
+                return preparedStatementExecutor.executeUpdate(inputGroups, executionContext.getSqlStatementContext(), executionContext.getRouteContext().getRouteUnits());
             } else {
                 return rawExecutor.executeUpdate(getRawInputGroups(), new RawSQLExecutorCallback());
             }
@@ -200,7 +200,7 @@ public final class ShardingSpherePreparedStatement extends AbstractPreparedState
                 Collection<InputGroup<StatementExecuteUnit>> inputGroups = getInputGroups();
                 cacheStatements(inputGroups);
                 reply();
-                return preparedStatementExecutor.execute(inputGroups, executionContext.getSqlStatementContext().getSqlStatement());
+                return preparedStatementExecutor.execute(inputGroups, executionContext.getSqlStatementContext().getSqlStatement(), executionContext.getRouteContext().getRouteUnits());
             } else {
                 // TODO process getStatement
                 return rawExecutor.execute(getRawInputGroups(), new RawSQLExecutorCallback());
diff --git a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSphereStatement.java b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSphereStatement.java
index 378e0b3..fb77574 100644
--- a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSphereStatement.java
+++ b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSphereStatement.java
@@ -148,7 +148,7 @@ public final class ShardingSphereStatement extends AbstractStatementAdapter {
             if (ExecutorConstant.MANAGED_RESOURCE) {
                 Collection<InputGroup<StatementExecuteUnit>> inputGroups = getInputGroups();
                 cacheStatements(inputGroups);
-                return statementExecutor.executeUpdate(inputGroups, executionContext.getSqlStatementContext());
+                return statementExecutor.executeUpdate(inputGroups, executionContext.getSqlStatementContext(), executionContext.getRouteContext().getRouteUnits());
             } else {
                 return rawExecutor.executeUpdate(getRawInputGroups(), new RawSQLExecutorCallback());
             }
@@ -167,7 +167,7 @@ public final class ShardingSphereStatement extends AbstractStatementAdapter {
             if (ExecutorConstant.MANAGED_RESOURCE) {
                 Collection<InputGroup<StatementExecuteUnit>> inputGroups = getInputGroups();
                 cacheStatements(inputGroups);
-                return statementExecutor.executeUpdate(inputGroups, executionContext.getSqlStatementContext(), autoGeneratedKeys);
+                return statementExecutor.executeUpdate(inputGroups, executionContext.getSqlStatementContext(), executionContext.getRouteContext().getRouteUnits(), autoGeneratedKeys);
             } else {
                 return rawExecutor.executeUpdate(getRawInputGroups(), new RawSQLExecutorCallback());
             }
@@ -184,7 +184,7 @@ public final class ShardingSphereStatement extends AbstractStatementAdapter {
             if (ExecutorConstant.MANAGED_RESOURCE) {
                 Collection<InputGroup<StatementExecuteUnit>> inputGroups = getInputGroups();
                 cacheStatements(inputGroups);
-                return statementExecutor.executeUpdate(inputGroups, executionContext.getSqlStatementContext(), columnIndexes);
+                return statementExecutor.executeUpdate(inputGroups, executionContext.getSqlStatementContext(), executionContext.getRouteContext().getRouteUnits(), columnIndexes);
             } else {
                 return rawExecutor.executeUpdate(getRawInputGroups(), new RawSQLExecutorCallback());
             }
@@ -201,7 +201,7 @@ public final class ShardingSphereStatement extends AbstractStatementAdapter {
             if (ExecutorConstant.MANAGED_RESOURCE) {
                 Collection<InputGroup<StatementExecuteUnit>> inputGroups = getInputGroups();
                 cacheStatements(inputGroups);
-                return statementExecutor.executeUpdate(inputGroups, executionContext.getSqlStatementContext(), columnNames);
+                return statementExecutor.executeUpdate(inputGroups, executionContext.getSqlStatementContext(), executionContext.getRouteContext().getRouteUnits(), columnNames);
             } else {
                 return rawExecutor.executeUpdate(getRawInputGroups(), new RawSQLExecutorCallback());
             }
@@ -217,7 +217,7 @@ public final class ShardingSphereStatement extends AbstractStatementAdapter {
             if (ExecutorConstant.MANAGED_RESOURCE) {
                 Collection<InputGroup<StatementExecuteUnit>> inputGroups = getInputGroups();
                 cacheStatements(inputGroups);
-                return statementExecutor.execute(inputGroups, executionContext.getSqlStatementContext().getSqlStatement());
+                return statementExecutor.execute(inputGroups, executionContext.getSqlStatementContext().getSqlStatement(), executionContext.getRouteContext().getRouteUnits());
             } else {
                 // TODO process getStatement
                 return rawExecutor.execute(getRawInputGroups(), new RawSQLExecutorCallback());
@@ -237,7 +237,7 @@ public final class ShardingSphereStatement extends AbstractStatementAdapter {
             if (ExecutorConstant.MANAGED_RESOURCE) {
                 Collection<InputGroup<StatementExecuteUnit>> inputGroups = getInputGroups();
                 cacheStatements(inputGroups);
-                return statementExecutor.execute(inputGroups, executionContext.getSqlStatementContext().getSqlStatement(), autoGeneratedKeys);
+                return statementExecutor.execute(inputGroups, executionContext.getSqlStatementContext().getSqlStatement(), executionContext.getRouteContext().getRouteUnits(), autoGeneratedKeys);
             } else {
                 // TODO process getStatement
                 return rawExecutor.execute(getRawInputGroups(), new RawSQLExecutorCallback());
@@ -255,7 +255,7 @@ public final class ShardingSphereStatement extends AbstractStatementAdapter {
             if (ExecutorConstant.MANAGED_RESOURCE) {
                 Collection<InputGroup<StatementExecuteUnit>> inputGroups = getInputGroups();
                 cacheStatements(inputGroups);
-                return statementExecutor.execute(inputGroups, executionContext.getSqlStatementContext().getSqlStatement(), columnIndexes);
+                return statementExecutor.execute(inputGroups, executionContext.getSqlStatementContext().getSqlStatement(), executionContext.getRouteContext().getRouteUnits(), columnIndexes);
             } else {
                 // TODO process getStatement
                 return rawExecutor.execute(getRawInputGroups(), new RawSQLExecutorCallback());
@@ -273,7 +273,7 @@ public final class ShardingSphereStatement extends AbstractStatementAdapter {
             if (ExecutorConstant.MANAGED_RESOURCE) {
                 Collection<InputGroup<StatementExecuteUnit>> inputGroups = getInputGroups();
                 cacheStatements(inputGroups);
-                return statementExecutor.execute(inputGroups, executionContext.getSqlStatementContext().getSqlStatement(), columnNames);
+                return statementExecutor.execute(inputGroups, executionContext.getSqlStatementContext().getSqlStatement(), executionContext.getRouteContext().getRouteUnits(), columnNames);
             } else {
                 // TODO process getStatement
                 return rawExecutor.execute(getRawInputGroups(), new RawSQLExecutorCallback());
diff --git a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/test/java/org/apache/shardingsphere/driver/executor/PreparedStatementExecutorTest.java b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/test/java/org/apache/shardingsphere/driver/executor/PreparedStatementExecutorTest.java
index 4eb2795..77a49a7 100644
--- a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/test/java/org/apache/shardingsphere/driver/executor/PreparedStatementExecutorTest.java
+++ b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/test/java/org/apache/shardingsphere/driver/executor/PreparedStatementExecutorTest.java
@@ -17,14 +17,14 @@
 
 package org.apache.shardingsphere.driver.executor;
 
-import org.apache.shardingsphere.infra.executor.sql.resourced.jdbc.executor.SQLExecutor;
 import org.apache.shardingsphere.driver.jdbc.core.connection.ShardingSphereConnection;
-import org.apache.shardingsphere.infra.executor.sql.QueryResult;
-import org.apache.shardingsphere.infra.executor.sql.resourced.jdbc.StatementExecuteUnit;
+import org.apache.shardingsphere.infra.executor.kernel.InputGroup;
 import org.apache.shardingsphere.infra.executor.sql.ConnectionMode;
+import org.apache.shardingsphere.infra.executor.sql.QueryResult;
 import org.apache.shardingsphere.infra.executor.sql.context.ExecutionUnit;
 import org.apache.shardingsphere.infra.executor.sql.context.SQLUnit;
-import org.apache.shardingsphere.infra.executor.kernel.InputGroup;
+import org.apache.shardingsphere.infra.executor.sql.resourced.jdbc.StatementExecuteUnit;
+import org.apache.shardingsphere.infra.executor.sql.resourced.jdbc.executor.SQLExecutor;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
 import org.junit.Test;
 
@@ -66,8 +66,8 @@ public final class PreparedStatementExecutorTest extends AbstractBaseExecutorTes
     
     @Test
     public void assertNoStatement() throws SQLException {
-        assertFalse(actual.execute(Collections.emptyList(), mock(SQLStatement.class)));
-        assertThat(actual.executeUpdate(Collections.emptyList(), createSQLStatementContext()), is(0));
+        assertFalse(actual.execute(Collections.emptyList(), mock(SQLStatement.class), null));
+        assertThat(actual.executeUpdate(Collections.emptyList(), createSQLStatementContext(), null), is(0));
         assertThat(actual.executeQuery(Collections.emptyList()).size(), is(0));
     }
     
@@ -138,7 +138,7 @@ public final class PreparedStatementExecutorTest extends AbstractBaseExecutorTes
     public void assertExecuteUpdateForSinglePreparedStatementSuccess() throws SQLException {
         PreparedStatement preparedStatement = getPreparedStatement();
         when(preparedStatement.executeUpdate()).thenReturn(10);
-        assertThat(actual.executeUpdate(getExecuteGroups(Collections.singletonList(preparedStatement), false), createSQLStatementContext()), is(10));
+        assertThat(actual.executeUpdate(getExecuteGroups(Collections.singletonList(preparedStatement), false), createSQLStatementContext(), null), is(10));
         verify(preparedStatement).executeUpdate();
     }
     
@@ -148,7 +148,7 @@ public final class PreparedStatementExecutorTest extends AbstractBaseExecutorTes
         PreparedStatement preparedStatement2 = getPreparedStatement();
         when(preparedStatement1.executeUpdate()).thenReturn(10);
         when(preparedStatement2.executeUpdate()).thenReturn(20);
-        assertThat(actual.executeUpdate(getExecuteGroups(Arrays.asList(preparedStatement1, preparedStatement2), false), createSQLStatementContext()), is(30));
+        assertThat(actual.executeUpdate(getExecuteGroups(Arrays.asList(preparedStatement1, preparedStatement2), false), createSQLStatementContext(), null), is(30));
         verify(preparedStatement1).executeUpdate();
         verify(preparedStatement2).executeUpdate();
     }
@@ -158,7 +158,7 @@ public final class PreparedStatementExecutorTest extends AbstractBaseExecutorTes
         PreparedStatement preparedStatement = getPreparedStatement();
         SQLException ex = new SQLException("");
         when(preparedStatement.executeUpdate()).thenThrow(ex);
-        assertThat(actual.executeUpdate(getExecuteGroups(Collections.singletonList(preparedStatement), false), createSQLStatementContext()), is(0));
+        assertThat(actual.executeUpdate(getExecuteGroups(Collections.singletonList(preparedStatement), false), createSQLStatementContext(), null), is(0));
         verify(preparedStatement).executeUpdate();
     }
     
@@ -170,7 +170,7 @@ public final class PreparedStatementExecutorTest extends AbstractBaseExecutorTes
                 = new SQLException("");
         when(preparedStatement1.executeUpdate()).thenThrow(ex);
         when(preparedStatement2.executeUpdate()).thenThrow(ex);
-        assertThat(actual.executeUpdate(getExecuteGroups(Arrays.asList(preparedStatement1, preparedStatement2), false), createSQLStatementContext()), is(0));
+        assertThat(actual.executeUpdate(getExecuteGroups(Arrays.asList(preparedStatement1, preparedStatement2), false), createSQLStatementContext(), null), is(0));
         verify(preparedStatement1).executeUpdate();
         verify(preparedStatement2).executeUpdate();
     }
@@ -179,7 +179,7 @@ public final class PreparedStatementExecutorTest extends AbstractBaseExecutorTes
     public void assertExecuteForSinglePreparedStatementSuccessWithDML() throws SQLException {
         PreparedStatement preparedStatement = getPreparedStatement();
         when(preparedStatement.execute()).thenReturn(false);
-        assertFalse(actual.execute(getExecuteGroups(Collections.singletonList(preparedStatement), false), mock(SQLStatement.class)));
+        assertFalse(actual.execute(getExecuteGroups(Collections.singletonList(preparedStatement), false), mock(SQLStatement.class), null));
         verify(preparedStatement).execute();
     }
     
@@ -189,7 +189,7 @@ public final class PreparedStatementExecutorTest extends AbstractBaseExecutorTes
         PreparedStatement preparedStatement2 = getPreparedStatement();
         when(preparedStatement1.execute()).thenReturn(false);
         when(preparedStatement2.execute()).thenReturn(false);
-        assertFalse(actual.execute(getExecuteGroups(Arrays.asList(preparedStatement1, preparedStatement2), false), mock(SQLStatement.class)));
+        assertFalse(actual.execute(getExecuteGroups(Arrays.asList(preparedStatement1, preparedStatement2), false), mock(SQLStatement.class), null));
         verify(preparedStatement1).execute();
         verify(preparedStatement2).execute();
     }
@@ -199,7 +199,7 @@ public final class PreparedStatementExecutorTest extends AbstractBaseExecutorTes
         PreparedStatement preparedStatement = getPreparedStatement();
         SQLException ex = new SQLException("");
         when(preparedStatement.execute()).thenThrow(ex);
-        assertFalse(actual.execute(getExecuteGroups(Collections.singletonList(preparedStatement), false), mock(SQLStatement.class)));
+        assertFalse(actual.execute(getExecuteGroups(Collections.singletonList(preparedStatement), false), mock(SQLStatement.class), null));
         verify(preparedStatement).execute();
     }
     
@@ -210,7 +210,7 @@ public final class PreparedStatementExecutorTest extends AbstractBaseExecutorTes
         SQLException ex = new SQLException("");
         when(preparedStatement1.execute()).thenThrow(ex);
         when(preparedStatement2.execute()).thenThrow(ex);
-        assertFalse(actual.execute(getExecuteGroups(Arrays.asList(preparedStatement1, preparedStatement2), false), mock(SQLStatement.class)));
+        assertFalse(actual.execute(getExecuteGroups(Arrays.asList(preparedStatement1, preparedStatement2), false), mock(SQLStatement.class), null));
         verify(preparedStatement1).execute();
         verify(preparedStatement2).execute();
     }
@@ -219,7 +219,7 @@ public final class PreparedStatementExecutorTest extends AbstractBaseExecutorTes
     public void assertExecuteForSinglePreparedStatementWithDQL() throws SQLException {
         PreparedStatement preparedStatement = getPreparedStatement();
         when(preparedStatement.execute()).thenReturn(true);
-        assertTrue(actual.execute(getExecuteGroups(Collections.singletonList(preparedStatement), true), mock(SQLStatement.class)));
+        assertTrue(actual.execute(getExecuteGroups(Collections.singletonList(preparedStatement), true), mock(SQLStatement.class), null));
         verify(preparedStatement).execute();
     }
     
@@ -229,7 +229,7 @@ public final class PreparedStatementExecutorTest extends AbstractBaseExecutorTes
         PreparedStatement preparedStatement2 = getPreparedStatement();
         when(preparedStatement1.execute()).thenReturn(true);
         when(preparedStatement2.execute()).thenReturn(true);
-        assertTrue(actual.execute(getExecuteGroups(Arrays.asList(preparedStatement1, preparedStatement2), true), mock(SQLStatement.class)));
+        assertTrue(actual.execute(getExecuteGroups(Arrays.asList(preparedStatement1, preparedStatement2), true), mock(SQLStatement.class), null));
         verify(preparedStatement1).execute();
         verify(preparedStatement2).execute();
     }
diff --git a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/test/java/org/apache/shardingsphere/driver/executor/StatementExecutorTest.java b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/test/java/org/apache/shardingsphere/driver/executor/StatementExecutorTest.java
index fccd321..8b21b52 100644
--- a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/test/java/org/apache/shardingsphere/driver/executor/StatementExecutorTest.java
+++ b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/test/java/org/apache/shardingsphere/driver/executor/StatementExecutorTest.java
@@ -68,8 +68,8 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest {
     
     @Test
     public void assertNoStatement() throws SQLException {
-        assertFalse(actual.execute(Collections.emptyList(), mock(SQLStatement.class)));
-        assertThat(actual.executeUpdate(Collections.emptyList(), createSQLStatementContext()), is(0));
+        assertFalse(actual.execute(Collections.emptyList(), mock(SQLStatement.class), null));
+        assertThat(actual.executeUpdate(Collections.emptyList(), createSQLStatementContext(), null), is(0));
         assertThat(actual.executeQuery(Collections.emptyList()).size(), is(0));
     }
     
@@ -141,7 +141,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest {
     public void assertExecuteUpdateForSingleStatementSuccess() throws SQLException {
         Statement statement = getStatement();
         when(statement.executeUpdate(DML_SQL)).thenReturn(10);
-        assertThat(actual.executeUpdate(getExecuteGroups(Collections.singletonList(statement), false), createSQLStatementContext()), is(10));
+        assertThat(actual.executeUpdate(getExecuteGroups(Collections.singletonList(statement), false), createSQLStatementContext(), null), is(10));
         verify(statement).executeUpdate(DML_SQL);
     }
     
@@ -151,7 +151,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest {
         Statement statement2 = getStatement();
         when(statement1.executeUpdate(DML_SQL)).thenReturn(10);
         when(statement2.executeUpdate(DML_SQL)).thenReturn(20);
-        assertThat(actual.executeUpdate(getExecuteGroups(Arrays.asList(statement1, statement2), false), createSQLStatementContext()), is(30));
+        assertThat(actual.executeUpdate(getExecuteGroups(Arrays.asList(statement1, statement2), false), createSQLStatementContext(), null), is(30));
         verify(statement1).executeUpdate(DML_SQL);
         verify(statement2).executeUpdate(DML_SQL);
     }
@@ -161,7 +161,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest {
         Statement statement = getStatement();
         SQLException ex = new SQLException("");
         when(statement.executeUpdate(DML_SQL)).thenThrow(ex);
-        assertThat(actual.executeUpdate(getExecuteGroups(Collections.singletonList(statement), false), createSQLStatementContext()), is(0));
+        assertThat(actual.executeUpdate(getExecuteGroups(Collections.singletonList(statement), false), createSQLStatementContext(), null), is(0));
         verify(statement).executeUpdate(DML_SQL);
     }
     
@@ -172,7 +172,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest {
         SQLException ex = new SQLException("");
         when(statement1.executeUpdate(DML_SQL)).thenThrow(ex);
         when(statement2.executeUpdate(DML_SQL)).thenThrow(ex);
-        assertThat(actual.executeUpdate(getExecuteGroups(Arrays.asList(statement1, statement2), false), createSQLStatementContext()), is(0));
+        assertThat(actual.executeUpdate(getExecuteGroups(Arrays.asList(statement1, statement2), false), createSQLStatementContext(), null), is(0));
         verify(statement1).executeUpdate(DML_SQL);
         verify(statement2).executeUpdate(DML_SQL);
     }
@@ -181,7 +181,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest {
     public void assertExecuteUpdateWithAutoGeneratedKeys() throws SQLException {
         Statement statement = getStatement();
         when(statement.executeUpdate(DML_SQL, Statement.NO_GENERATED_KEYS)).thenReturn(10);
-        assertThat(actual.executeUpdate(getExecuteGroups(Collections.singletonList(statement), false), createSQLStatementContext(), Statement.NO_GENERATED_KEYS), is(10));
+        assertThat(actual.executeUpdate(getExecuteGroups(Collections.singletonList(statement), false), createSQLStatementContext(), null, Statement.NO_GENERATED_KEYS), is(10));
         verify(statement).executeUpdate(DML_SQL, Statement.NO_GENERATED_KEYS);
     }
     
@@ -189,7 +189,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest {
     public void assertExecuteUpdateWithColumnIndexes() throws SQLException {
         Statement statement = getStatement();
         when(statement.executeUpdate(DML_SQL, new int[] {1})).thenReturn(10);
-        assertThat(actual.executeUpdate(getExecuteGroups(Collections.singletonList(statement), false), createSQLStatementContext(), new int[] {1}), is(10));
+        assertThat(actual.executeUpdate(getExecuteGroups(Collections.singletonList(statement), false), createSQLStatementContext(), null, new int[] {1}), is(10));
         verify(statement).executeUpdate(DML_SQL, new int[] {1});
     }
     
@@ -207,7 +207,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest {
     public void assertExecuteUpdateWithColumnNames() throws SQLException {
         Statement statement = getStatement();
         when(statement.executeUpdate(DML_SQL, new String[] {"col"})).thenReturn(10);
-        assertThat(actual.executeUpdate(getExecuteGroups(Collections.singletonList(statement), false), createSQLStatementContext(), new String[] {"col"}), is(10));
+        assertThat(actual.executeUpdate(getExecuteGroups(Collections.singletonList(statement), false), createSQLStatementContext(), null, new String[] {"col"}), is(10));
         verify(statement).executeUpdate(DML_SQL, new String[] {"col"});
     }
     
@@ -215,7 +215,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest {
     public void assertExecuteForSingleStatementSuccessWithDML() throws SQLException {
         Statement statement = getStatement();
         when(statement.execute(DML_SQL)).thenReturn(false);
-        assertFalse(actual.execute(getExecuteGroups(Collections.singletonList(statement), false), mock(SQLStatement.class)));
+        assertFalse(actual.execute(getExecuteGroups(Collections.singletonList(statement), false), mock(SQLStatement.class), null));
         verify(statement).execute(DML_SQL);
     }
     
@@ -225,7 +225,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest {
         Statement statement2 = getStatement();
         when(statement1.execute(DML_SQL)).thenReturn(false);
         when(statement2.execute(DML_SQL)).thenReturn(false);
-        assertFalse(actual.execute(getExecuteGroups(Arrays.asList(statement1, statement2), false), mock(SQLStatement.class)));
+        assertFalse(actual.execute(getExecuteGroups(Arrays.asList(statement1, statement2), false), mock(SQLStatement.class), null));
         verify(statement1).execute(DML_SQL);
         verify(statement2).execute(DML_SQL);
     }
@@ -235,7 +235,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest {
         Statement statement = getStatement();
         SQLException ex = new SQLException("");
         when(statement.execute(DML_SQL)).thenThrow(ex);
-        assertFalse(actual.execute(getExecuteGroups(Collections.singletonList(statement), false), mock(SQLStatement.class)));
+        assertFalse(actual.execute(getExecuteGroups(Collections.singletonList(statement), false), mock(SQLStatement.class), null));
         verify(statement).execute(DML_SQL);
     }
     
@@ -246,7 +246,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest {
         SQLException ex = new SQLException("");
         when(statement1.execute(DML_SQL)).thenThrow(ex);
         when(statement2.execute(DML_SQL)).thenThrow(ex);
-        assertFalse(actual.execute(getExecuteGroups(Arrays.asList(statement1, statement2), false), mock(SQLStatement.class)));
+        assertFalse(actual.execute(getExecuteGroups(Arrays.asList(statement1, statement2), false), mock(SQLStatement.class), null));
         verify(statement1).execute(DML_SQL);
         verify(statement2).execute(DML_SQL);
     }
@@ -255,7 +255,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest {
     public void assertExecuteForSingleStatementWithDQL() throws SQLException {
         Statement statement = getStatement();
         when(statement.execute(DQL_SQL)).thenReturn(true);
-        assertTrue(actual.execute(getExecuteGroups(Collections.singletonList(statement), true), mock(SQLStatement.class)));
+        assertTrue(actual.execute(getExecuteGroups(Collections.singletonList(statement), true), mock(SQLStatement.class), null));
         verify(statement).execute(DQL_SQL);
     }
     
@@ -265,7 +265,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest {
         Statement statement2 = getStatement();
         when(statement1.execute(DQL_SQL)).thenReturn(true);
         when(statement2.execute(DQL_SQL)).thenReturn(true);
-        assertTrue(actual.execute(getExecuteGroups(Arrays.asList(statement1, statement2), true), mock(SQLStatement.class)));
+        assertTrue(actual.execute(getExecuteGroups(Arrays.asList(statement1, statement2), true), mock(SQLStatement.class), null));
         verify(statement1).execute(DQL_SQL);
         verify(statement2).execute(DQL_SQL);
     }
@@ -274,7 +274,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest {
     public void assertExecuteWithAutoGeneratedKeys() throws SQLException {
         Statement statement = getStatement();
         when(statement.execute(DML_SQL, Statement.NO_GENERATED_KEYS)).thenReturn(false);
-        assertFalse(actual.execute(getExecuteGroups(Collections.singletonList(statement), false), mock(SQLStatement.class), Statement.NO_GENERATED_KEYS));
+        assertFalse(actual.execute(getExecuteGroups(Collections.singletonList(statement), false), mock(SQLStatement.class), null, Statement.NO_GENERATED_KEYS));
         verify(statement).execute(DML_SQL, Statement.NO_GENERATED_KEYS);
     }
 
@@ -282,7 +282,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest {
     public void assertExecuteWithColumnIndexes() throws SQLException {
         Statement statement = getStatement();
         when(statement.execute(DML_SQL, new int[] {1})).thenReturn(false);
-        assertFalse(actual.execute(getExecuteGroups(Collections.singletonList(statement), false), mock(SQLStatement.class), new int[] {1}));
+        assertFalse(actual.execute(getExecuteGroups(Collections.singletonList(statement), false), mock(SQLStatement.class), null, new int[] {1}));
         verify(statement).execute(DML_SQL, new int[] {1});
     }
     
@@ -290,7 +290,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest {
     public void assertExecuteWithColumnNames() throws SQLException {
         Statement statement = getStatement();
         when(statement.execute(DML_SQL, new String[] {"col"})).thenReturn(false);
-        assertFalse(actual.execute(getExecuteGroups(Collections.singletonList(statement), false), mock(SQLStatement.class), new String[] {"col"}));
+        assertFalse(actual.execute(getExecuteGroups(Collections.singletonList(statement), false), mock(SQLStatement.class), null, new String[] {"col"}));
         verify(statement).execute(DML_SQL, new String[] {"col"});
     }
     
@@ -301,7 +301,7 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest {
         SQLException ex = new SQLException("");
         when(statement.execute(DML_SQL)).thenThrow(ex);
         try {
-            assertFalse(actual.execute(getExecuteGroups(Collections.singletonList(statement), false), mock(SQLStatement.class)));
+            assertFalse(actual.execute(getExecuteGroups(Collections.singletonList(statement), false), mock(SQLStatement.class), null));
         } catch (final SQLException ignored) {
         }
     }
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/communication/jdbc/JDBCDatabaseCommunicationEngine.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/communication/jdbc/JDBCDatabaseCommunicationEngine.java
index a7b06ce..a694479 100644
--- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/communication/jdbc/JDBCDatabaseCommunicationEngine.java
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/communication/jdbc/JDBCDatabaseCommunicationEngine.java
@@ -20,7 +20,7 @@ package org.apache.shardingsphere.proxy.backend.communication.jdbc;
 import lombok.RequiredArgsConstructor;
 import org.apache.shardingsphere.governance.core.event.GovernanceEventBus;
 import org.apache.shardingsphere.governance.core.event.model.persist.MetaDataPersistEvent;
-import org.apache.shardingsphere.infra.metadata.model.physical.model.table.PhysicalTableMetaData;
+import org.apache.shardingsphere.infra.binder.LogicSQL;
 import org.apache.shardingsphere.infra.binder.statement.SQLStatementContext;
 import org.apache.shardingsphere.infra.config.properties.ConfigurationPropertyKey;
 import org.apache.shardingsphere.infra.context.kernel.KernelProcessor;
@@ -30,12 +30,14 @@ import org.apache.shardingsphere.infra.executor.sql.log.SQLLogger;
 import org.apache.shardingsphere.infra.executor.sql.raw.execute.result.query.QueryHeader;
 import org.apache.shardingsphere.infra.merge.MergeEngine;
 import org.apache.shardingsphere.infra.merge.result.MergedResult;
+import org.apache.shardingsphere.infra.metadata.model.logic.LogicSchemaMetaDataLoader;
+import org.apache.shardingsphere.infra.metadata.model.physical.model.table.PhysicalTableMetaData;
 import org.apache.shardingsphere.infra.metadata.refresh.MetaDataRefreshStrategy;
 import org.apache.shardingsphere.infra.metadata.refresh.MetaDataRefreshStrategyFactory;
-import org.apache.shardingsphere.infra.metadata.model.logic.LogicSchemaMetaDataLoader;
+import org.apache.shardingsphere.infra.route.context.RouteMapper;
+import org.apache.shardingsphere.infra.route.context.RouteUnit;
 import org.apache.shardingsphere.infra.rule.DataNodeRoutedRule;
 import org.apache.shardingsphere.infra.schema.ShardingSphereSchema;
-import org.apache.shardingsphere.infra.binder.LogicSQL;
 import org.apache.shardingsphere.proxy.backend.communication.DatabaseCommunicationEngine;
 import org.apache.shardingsphere.proxy.backend.communication.jdbc.execute.SQLExecuteEngine;
 import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
@@ -47,8 +49,10 @@ import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
 
 import java.sql.SQLException;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 import java.util.Optional;
+import java.util.stream.Collectors;
 
 /**
  * Database access engine for JDBC.
@@ -87,19 +91,21 @@ public final class JDBCDatabaseCommunicationEngine implements DatabaseCommunicat
         }
         sqlExecuteEngine.checkExecutePrerequisites(executionContext);
         response = sqlExecuteEngine.execute(executionContext);
-        refreshTableMetaData(executionContext.getSqlStatementContext().getSqlStatement());
+        Collection<String> routeDataSourceNames = executionContext.getRouteContext().getRouteUnits().stream()
+                .map(RouteUnit::getDataSourceMapper).map(RouteMapper::getLogicName).collect(Collectors.toList());
+        refreshTableMetaData(executionContext.getSqlStatementContext().getSqlStatement(), routeDataSourceNames);
         return merge(executionContext.getSqlStatementContext());
     }
     
     @SuppressWarnings({"unchecked", "rawtypes"})
-    private void refreshTableMetaData(final SQLStatement sqlStatement) throws SQLException {
+    private void refreshTableMetaData(final SQLStatement sqlStatement, final Collection<String> routeDataSourceNames) throws SQLException {
         if (null == sqlStatement) {
             return;
         }
         Optional<MetaDataRefreshStrategy> refreshStrategy = MetaDataRefreshStrategyFactory.newInstance(sqlStatement);
         if (refreshStrategy.isPresent()) {
             refreshStrategy.get().refreshMetaData(
-                    schema.getMetaData(), ProxyContext.getInstance().getSchemaContexts().getDatabaseType(), schema.getDataSources(), sqlStatement, this::loadTableMetaData);
+                    schema.getMetaData(), ProxyContext.getInstance().getSchemaContexts().getDatabaseType(), routeDataSourceNames, sqlStatement, this::loadTableMetaData);
             GovernanceEventBus.getInstance().post(new MetaDataPersistEvent(schema.getName(), schema.getMetaData().getSchemaMetaData()));
         }
     }