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

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


The following commit(s) were added to refs/heads/master by this push:
     new e814312089 [IOTDB-3255] Turn off MLog and Implement snapshot while 
using Ratis (#6337)
e814312089 is described below

commit e814312089c99e1059e942fea43acdb2a86d068c
Author: Marcos_Zyk <[email protected]>
AuthorDate: Mon Jun 20 21:26:20 2022 +0800

    [IOTDB-3255] Turn off MLog and Implement snapshot while using Ratis (#6337)
    
    * implement mLog switch
    
    * implement mtree ser/deser
    
    * implement snapshot process
    
    * implement snapshot
    
    * add log
    
    Co-authored-by: Jinrui.Zhang <[email protected]>
---
 .../schemaregion/rocksdb/mnode/RMNode.java         |   7 +
 .../apache/iotdb/db/metadata/MetadataConstant.java |  20 +-
 .../idtable/entry/InsertMeasurementMNode.java      |   6 +
 .../iotdb/db/metadata/logfile/MLogWriter.java      |   2 +-
 .../iotdb/db/metadata/mnode/EntityMNode.java       |   6 +
 .../org/apache/iotdb/db/metadata/mnode/IMNode.java |   3 +
 .../iotdb/db/metadata/mnode/InternalMNode.java     |   6 +
 .../iotdb/db/metadata/mnode/MeasurementMNode.java  |   6 +
 .../db/metadata/mnode/StorageGroupEntityMNode.java |   6 +
 .../iotdb/db/metadata/mnode/StorageGroupMNode.java |   6 +
 .../db/metadata/mnode/visitor/MNodeVisitor.java    |  39 +++
 .../db/metadata/mtree/MTreeBelowSGMemoryImpl.java  |  28 ++
 .../mtree/snapshot/MemMTreeSnapshotUtil.java       | 347 +++++++++++++++++++++
 .../db/metadata/mtree/store/CachedMTreeStore.java  |   7 +
 .../iotdb/db/metadata/mtree/store/IMTreeStore.java |   4 +
 .../db/metadata/mtree/store/MemMTreeStore.java     |  18 ++
 .../db/metadata/schemaregion/SchemaEngine.java     |   7 +-
 .../schemaregion/SchemaRegionMemoryImpl.java       | 276 +++++++++-------
 .../apache/iotdb/db/metadata/tag/TagManager.java   |  19 ++
 .../db/metadata/upgrade/MetadataUpgrader.java      |   4 +-
 .../db/metadata/schemaRegion/SchemaRegionTest.java |  70 ++++-
 .../db/metadata/upgrade/MetadataUpgradeTest.java   |   9 +-
 server/src/test/resources/logback-test.xml         |   1 +
 23 files changed, 765 insertions(+), 132 deletions(-)

diff --git 
a/schema-engine-rocksdb/src/main/java/org/apache/iotdb/db/metadata/schemaregion/rocksdb/mnode/RMNode.java
 
b/schema-engine-rocksdb/src/main/java/org/apache/iotdb/db/metadata/schemaregion/rocksdb/mnode/RMNode.java
index 5d66327dc1..aea541e7b9 100644
--- 
a/schema-engine-rocksdb/src/main/java/org/apache/iotdb/db/metadata/schemaregion/rocksdb/mnode/RMNode.java
+++ 
b/schema-engine-rocksdb/src/main/java/org/apache/iotdb/db/metadata/schemaregion/rocksdb/mnode/RMNode.java
@@ -28,6 +28,7 @@ import org.apache.iotdb.db.metadata.mnode.IMNode;
 import org.apache.iotdb.db.metadata.mnode.IMeasurementMNode;
 import org.apache.iotdb.db.metadata.mnode.IStorageGroupMNode;
 import org.apache.iotdb.db.metadata.mnode.container.IMNodeContainer;
+import org.apache.iotdb.db.metadata.mnode.visitor.MNodeVisitor;
 import org.apache.iotdb.db.metadata.mtree.store.disk.cache.CacheEntry;
 import org.apache.iotdb.db.metadata.schemaregion.rocksdb.RSchemaConstants;
 import 
org.apache.iotdb.db.metadata.schemaregion.rocksdb.RSchemaReadWriteHandler;
@@ -250,5 +251,11 @@ public abstract class RMNode implements IMNode {
   public void setChildren(IMNodeContainer children) {
     throw new UnsupportedOperationException("Temporarily unsupported");
   }
+
+  @Override
+  public <R, C> R accept(MNodeVisitor<R, C> visitor, C context) {
+    throw new UnsupportedOperationException("RMNode doesn't support this 
method");
+  }
+
   // end
 }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/metadata/MetadataConstant.java 
b/server/src/main/java/org/apache/iotdb/db/metadata/MetadataConstant.java
index ffc2e58dd1..f4974cc67e 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/MetadataConstant.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/MetadataConstant.java
@@ -27,19 +27,19 @@ public class MetadataConstant {
     // allowed to do nothing
   }
 
+  public static final String MTREE_PREFIX = "mtree";
   private static final String MTREE_VERSION = "1";
+  public static final String MTREE_TXT_SNAPSHOT_OLD_VERSION =
+      MTREE_PREFIX + IoTDBConstant.FILE_NAME_SEPARATOR + MTREE_VERSION + 
".snapshot";
+  public static final String MTREE_SNAPSHOT_OLD_VERSION =
+      MTREE_PREFIX + IoTDBConstant.FILE_NAME_SEPARATOR + MTREE_VERSION + 
".snapshot.bin";
+  public static final String MTREE_SNAPSHOT_TMP_OLDVERSION =
+      MTREE_PREFIX + IoTDBConstant.FILE_NAME_SEPARATOR + MTREE_VERSION + 
".snapshot.bin.tmp";
 
   public static final String ROOT = "root";
   public static final String METADATA_TXT_LOG = "mlog.txt";
   public static final String METADATA_LOG = "mlog.bin";
   public static final String TAG_LOG = "tlog.txt";
-  public static final String MTREE_PREFIX = "mtree";
-  public static final String MTREE_TXT_SNAPSHOT =
-      MTREE_PREFIX + IoTDBConstant.FILE_NAME_SEPARATOR + MTREE_VERSION + 
".snapshot";
-  public static final String MTREE_SNAPSHOT =
-      MTREE_PREFIX + IoTDBConstant.FILE_NAME_SEPARATOR + MTREE_VERSION + 
".snapshot.bin";
-  public static final String MTREE_SNAPSHOT_TMP =
-      MTREE_PREFIX + IoTDBConstant.FILE_NAME_SEPARATOR + MTREE_VERSION + 
".snapshot.bin.tmp";
   public static final String TEMPLATE_FILE = "template_log.bin";
   public static final String STORAGE_GROUP_LOG = "storage_group_log.bin";
   public static final String SCHEMA_FILE_NAME = "schema_file.pst";
@@ -49,6 +49,8 @@ public class MetadataConstant {
   public static final String METADATA_LOG_SNAPSHOT_TMP = 
"mlog.bin.snapshot.tmp";
   public static final String TAG_LOG_SNAPSHOT = "tlog.txt.snapshot";
   public static final String TAG_LOG_SNAPSHOT_TMP = "tlog.txt.snapshot.tmp";
+  public static final String MTREE_SNAPSHOT = "mtree.snapshot";
+  public static final String MTREE_SNAPSHOT_TMP = "mtree.snapshot.tmp";
 
   public static final String[] ALL_RESULT_NODES = new String[] {"root", "**"};
   public static final PartialPath ALL_MATCH_PATTERN = new PartialPath(new 
String[] {"root", "**"});
@@ -57,11 +59,13 @@ public class MetadataConstant {
   public static final byte STORAGE_GROUP_MNODE_TYPE = 1;
   public static final byte MEASUREMENT_MNODE_TYPE = 2;
   public static final byte ENTITY_MNODE_TYPE = 3;
+  public static final byte STORAGE_GROUP_ENTITY_MNODE_TYPE = 4;
 
   public static final String INTERNAL_MNODE_TYPE_NAME = "InternalMNode";
   public static final String STORAGE_GROUP_MNODE_TYPE_NAME = 
"StorageGroupMNode";
   public static final String MEASUREMENT_MNODE_TYPE_NAME = "MeasurementMNode";
   public static final String ENTITY_MNODE_TYPE_NAME = "EntityMNode";
+  public static final String STORAGE_GROUP_ENTITY_MNODE_TYPE_NAME = 
"StorageGroupEntityMNode";
 
   public static String getMNodeTypeName(byte type) {
     switch (type) {
@@ -73,6 +77,8 @@ public class MetadataConstant {
         return MEASUREMENT_MNODE_TYPE_NAME;
       case ENTITY_MNODE_TYPE:
         return ENTITY_MNODE_TYPE_NAME;
+      case STORAGE_GROUP_ENTITY_MNODE_TYPE:
+        return STORAGE_GROUP_ENTITY_MNODE_TYPE_NAME;
       default:
         throw new RuntimeException("Undefined MNode type " + type);
     }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/metadata/idtable/entry/InsertMeasurementMNode.java
 
b/server/src/main/java/org/apache/iotdb/db/metadata/idtable/entry/InsertMeasurementMNode.java
index dfc48e03fc..abd844f820 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/metadata/idtable/entry/InsertMeasurementMNode.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/metadata/idtable/entry/InsertMeasurementMNode.java
@@ -29,6 +29,7 @@ import org.apache.iotdb.db.metadata.mnode.IMNode;
 import org.apache.iotdb.db.metadata.mnode.IMeasurementMNode;
 import org.apache.iotdb.db.metadata.mnode.IStorageGroupMNode;
 import org.apache.iotdb.db.metadata.mnode.container.IMNodeContainer;
+import org.apache.iotdb.db.metadata.mnode.visitor.MNodeVisitor;
 import org.apache.iotdb.db.metadata.mtree.store.disk.cache.CacheEntry;
 import org.apache.iotdb.db.metadata.path.MeasurementPath;
 import org.apache.iotdb.db.metadata.template.Template;
@@ -262,6 +263,11 @@ public class InsertMeasurementMNode implements 
IMeasurementMNode {
   @Override
   public void setCacheEntry(CacheEntry cacheEntry) {}
 
+  @Override
+  public <R, C> R accept(MNodeVisitor<R, C> visitor, C context) {
+    throw new UnsupportedOperationException("insert measurement mnode doesn't 
support this method");
+  }
+
   @Override
   public MeasurementPath getMeasurementPath() {
     throw new UnsupportedOperationException("insert measurement mnode doesn't 
support this method");
diff --git 
a/server/src/main/java/org/apache/iotdb/db/metadata/logfile/MLogWriter.java 
b/server/src/main/java/org/apache/iotdb/db/metadata/logfile/MLogWriter.java
index 8a24be8785..cdb9031bcd 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/logfile/MLogWriter.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/logfile/MLogWriter.java
@@ -119,7 +119,7 @@ public class MLogWriter implements AutoCloseable {
     mlogBuffer.clear();
   }
 
-  synchronized void putLog(PhysicalPlan plan) throws IOException {
+  public synchronized void putLog(PhysicalPlan plan) throws IOException {
     try {
       plan.serialize(mlogBuffer);
       sync();
diff --git 
a/server/src/main/java/org/apache/iotdb/db/metadata/mnode/EntityMNode.java 
b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/EntityMNode.java
index 73fe5e23db..9dda06ed98 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/mnode/EntityMNode.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/EntityMNode.java
@@ -20,6 +20,7 @@ package org.apache.iotdb.db.metadata.mnode;
 
 import org.apache.iotdb.db.metadata.lastCache.container.ILastCacheContainer;
 import org.apache.iotdb.db.metadata.lastCache.container.LastCacheContainer;
+import org.apache.iotdb.db.metadata.mnode.visitor.MNodeVisitor;
 
 import java.util.Collections;
 import java.util.Map;
@@ -160,4 +161,9 @@ public class EntityMNode extends InternalMNode implements 
IEntityMNode {
   public boolean isEntity() {
     return true;
   }
+
+  @Override
+  public <R, C> R accept(MNodeVisitor<R, C> visitor, C context) {
+    return visitor.visitEntityMNode(this, context);
+  }
 }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/metadata/mnode/IMNode.java 
b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/IMNode.java
index bb979305e3..4ecee98267 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/mnode/IMNode.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/IMNode.java
@@ -22,6 +22,7 @@ import org.apache.iotdb.commons.path.PartialPath;
 import org.apache.iotdb.db.engine.trigger.executor.TriggerExecutor;
 import org.apache.iotdb.db.metadata.logfile.MLogWriter;
 import org.apache.iotdb.db.metadata.mnode.container.IMNodeContainer;
+import org.apache.iotdb.db.metadata.mnode.visitor.MNodeVisitor;
 import org.apache.iotdb.db.metadata.mtree.store.disk.cache.CacheEntry;
 import org.apache.iotdb.db.metadata.template.Template;
 
@@ -100,4 +101,6 @@ public interface IMNode extends Serializable {
   CacheEntry getCacheEntry();
 
   void setCacheEntry(CacheEntry cacheEntry);
+
+  <R, C> R accept(MNodeVisitor<R, C> visitor, C context);
 }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/metadata/mnode/InternalMNode.java 
b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/InternalMNode.java
index e478444c3b..99dde9ab9e 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/mnode/InternalMNode.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/InternalMNode.java
@@ -21,6 +21,7 @@ package org.apache.iotdb.db.metadata.mnode;
 import org.apache.iotdb.db.metadata.logfile.MLogWriter;
 import org.apache.iotdb.db.metadata.mnode.container.IMNodeContainer;
 import org.apache.iotdb.db.metadata.mnode.container.MNodeContainers;
+import org.apache.iotdb.db.metadata.mnode.visitor.MNodeVisitor;
 import org.apache.iotdb.db.metadata.template.Template;
 import org.apache.iotdb.db.qp.physical.sys.MNodePlan;
 
@@ -227,6 +228,11 @@ public class InternalMNode extends MNode {
     logWriter.serializeMNode(this);
   }
 
+  @Override
+  public <R, C> R accept(MNodeVisitor<R, C> visitor, C context) {
+    return visitor.visitInternalMNode(this, context);
+  }
+
   void serializeChildren(MLogWriter logWriter) throws IOException {
     if (children == null) {
       return;
diff --git 
a/server/src/main/java/org/apache/iotdb/db/metadata/mnode/MeasurementMNode.java 
b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/MeasurementMNode.java
index 3909f0a471..5863e3aa31 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/metadata/mnode/MeasurementMNode.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/MeasurementMNode.java
@@ -24,6 +24,7 @@ import 
org.apache.iotdb.db.metadata.lastCache.container.LastCacheContainer;
 import org.apache.iotdb.db.metadata.logfile.MLogWriter;
 import org.apache.iotdb.db.metadata.mnode.container.IMNodeContainer;
 import org.apache.iotdb.db.metadata.mnode.container.MNodeContainers;
+import org.apache.iotdb.db.metadata.mnode.visitor.MNodeVisitor;
 import org.apache.iotdb.db.metadata.path.MeasurementPath;
 import org.apache.iotdb.db.metadata.template.Template;
 import org.apache.iotdb.db.qp.physical.sys.MeasurementMNodePlan;
@@ -153,6 +154,11 @@ public class MeasurementMNode extends MNode implements 
IMeasurementMNode {
     logWriter.serializeMeasurementMNode(this);
   }
 
+  @Override
+  public <R, C> R accept(MNodeVisitor<R, C> visitor, C context) {
+    return visitor.visitMeasurementMNode(this, context);
+  }
+
   /** deserialize MeasurementMNode from MeasurementNodePlan */
   public static IMeasurementMNode deserializeFrom(MeasurementMNodePlan plan) {
     IMeasurementMNode node =
diff --git 
a/server/src/main/java/org/apache/iotdb/db/metadata/mnode/StorageGroupEntityMNode.java
 
b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/StorageGroupEntityMNode.java
index 492ccff92f..6de14c8297 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/metadata/mnode/StorageGroupEntityMNode.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/StorageGroupEntityMNode.java
@@ -20,6 +20,7 @@ package org.apache.iotdb.db.metadata.mnode;
 
 import org.apache.iotdb.confignode.rpc.thrift.TStorageGroupSchema;
 import org.apache.iotdb.db.metadata.logfile.MLogWriter;
+import org.apache.iotdb.db.metadata.mnode.visitor.MNodeVisitor;
 
 import java.io.IOException;
 
@@ -86,4 +87,9 @@ public class StorageGroupEntityMNode extends EntityMNode 
implements IStorageGrou
 
     logWriter.serializeStorageGroupMNode(this);
   }
+
+  @Override
+  public <R, C> R accept(MNodeVisitor<R, C> visitor, C context) {
+    return visitor.visitStorageGroupEntityMNode(this, context);
+  }
 }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/metadata/mnode/StorageGroupMNode.java
 
b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/StorageGroupMNode.java
index 7139ef54a5..617505a645 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/metadata/mnode/StorageGroupMNode.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/StorageGroupMNode.java
@@ -20,6 +20,7 @@ package org.apache.iotdb.db.metadata.mnode;
 
 import org.apache.iotdb.confignode.rpc.thrift.TStorageGroupSchema;
 import org.apache.iotdb.db.metadata.logfile.MLogWriter;
+import org.apache.iotdb.db.metadata.mnode.visitor.MNodeVisitor;
 import org.apache.iotdb.db.qp.physical.sys.StorageGroupMNodePlan;
 
 import java.io.IOException;
@@ -107,4 +108,9 @@ public class StorageGroupMNode extends InternalMNode 
implements IStorageGroupMNo
   public static StorageGroupMNode deserializeFrom(String[] nodeInfo) {
     return new StorageGroupMNode(null, nodeInfo[1], 
Long.parseLong(nodeInfo[2]));
   }
+
+  @Override
+  public <R, C> R accept(MNodeVisitor<R, C> visitor, C context) {
+    return visitor.visitStorageGroupMNode(this, context);
+  }
 }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/metadata/mnode/visitor/MNodeVisitor.java
 
b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/visitor/MNodeVisitor.java
new file mode 100644
index 0000000000..53ccc1f059
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/visitor/MNodeVisitor.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.metadata.mnode.visitor;
+
+import org.apache.iotdb.db.metadata.mnode.EntityMNode;
+import org.apache.iotdb.db.metadata.mnode.InternalMNode;
+import org.apache.iotdb.db.metadata.mnode.MeasurementMNode;
+import org.apache.iotdb.db.metadata.mnode.StorageGroupEntityMNode;
+import org.apache.iotdb.db.metadata.mnode.StorageGroupMNode;
+
+public abstract class MNodeVisitor<R, C> {
+
+  public abstract R visitInternalMNode(InternalMNode node, C context);
+
+  public abstract R visitStorageGroupMNode(StorageGroupMNode node, C context);
+
+  public abstract R visitStorageGroupEntityMNode(StorageGroupEntityMNode node, 
C context);
+
+  public abstract R visitEntityMNode(EntityMNode node, C context);
+
+  public abstract R visitMeasurementMNode(MeasurementMNode node, C context);
+}
diff --git 
a/server/src/main/java/org/apache/iotdb/db/metadata/mtree/MTreeBelowSGMemoryImpl.java
 
b/server/src/main/java/org/apache/iotdb/db/metadata/mtree/MTreeBelowSGMemoryImpl.java
index ab1f2d0e37..87b44df95c 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/metadata/mtree/MTreeBelowSGMemoryImpl.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/metadata/mtree/MTreeBelowSGMemoryImpl.java
@@ -64,6 +64,8 @@ import org.apache.iotdb.tsfile.utils.Pair;
 import org.apache.iotdb.tsfile.write.schema.IMeasurementSchema;
 import org.apache.iotdb.tsfile.write.schema.MeasurementSchema;
 
+import java.io.File;
+import java.io.IOException;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -76,6 +78,7 @@ import java.util.Map;
 import java.util.Queue;
 import java.util.Set;
 import java.util.TreeSet;
+import java.util.function.Consumer;
 import java.util.stream.Stream;
 
 import static java.util.stream.Collectors.toList;
@@ -125,11 +128,36 @@ public class MTreeBelowSGMemoryImpl implements 
IMTreeBelowSG {
     levelOfSG = storageGroup.getNodeLength() - 1;
   }
 
+  private MTreeBelowSGMemoryImpl(
+      MemMTreeStore store, IStorageGroupMNode storageGroupMNode, int 
schemaRegionId) {
+    this.store = store;
+    this.storageGroupMNode = store.getRoot().getAsStorageGroupMNode();
+    this.storageGroupMNode.setParent(storageGroupMNode.getParent());
+    levelOfSG = storageGroupMNode.getPartialPath().getNodeLength() - 1;
+  }
+
   @Override
   public void clear() {
     store.clear();
     storageGroupMNode = null;
   }
+
+  public synchronized boolean createSnapshot(File snapshotDir) {
+    return store.createSnapshot(snapshotDir);
+  }
+
+  public static MTreeBelowSGMemoryImpl loadFromSnapshot(
+      File snapshotDir,
+      IStorageGroupMNode storageGroupMNode,
+      int schemaRegionId,
+      Consumer<IMeasurementMNode> measurementProcess)
+      throws IOException {
+    return new MTreeBelowSGMemoryImpl(
+        MemMTreeStore.loadFromSnapshot(snapshotDir, measurementProcess),
+        storageGroupMNode,
+        schemaRegionId);
+  }
+
   // endregion
 
   // region Timeseries operation, including create and delete
diff --git 
a/server/src/main/java/org/apache/iotdb/db/metadata/mtree/snapshot/MemMTreeSnapshotUtil.java
 
b/server/src/main/java/org/apache/iotdb/db/metadata/mtree/snapshot/MemMTreeSnapshotUtil.java
new file mode 100644
index 0000000000..f5fb4876d4
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/metadata/mtree/snapshot/MemMTreeSnapshotUtil.java
@@ -0,0 +1,347 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.metadata.mtree.snapshot;
+
+import org.apache.iotdb.commons.file.SystemFileFactory;
+import org.apache.iotdb.db.metadata.MetadataConstant;
+import org.apache.iotdb.db.metadata.mnode.EntityMNode;
+import org.apache.iotdb.db.metadata.mnode.IMNode;
+import org.apache.iotdb.db.metadata.mnode.IMeasurementMNode;
+import org.apache.iotdb.db.metadata.mnode.InternalMNode;
+import org.apache.iotdb.db.metadata.mnode.MeasurementMNode;
+import org.apache.iotdb.db.metadata.mnode.StorageGroupEntityMNode;
+import org.apache.iotdb.db.metadata.mnode.StorageGroupMNode;
+import org.apache.iotdb.db.metadata.mnode.iterator.IMNodeIterator;
+import org.apache.iotdb.db.metadata.mnode.visitor.MNodeVisitor;
+import org.apache.iotdb.db.metadata.mtree.store.MemMTreeStore;
+import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
+import org.apache.iotdb.tsfile.write.schema.MeasurementSchema;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.function.Consumer;
+
+import static org.apache.iotdb.db.metadata.MetadataConstant.ENTITY_MNODE_TYPE;
+import static 
org.apache.iotdb.db.metadata.MetadataConstant.INTERNAL_MNODE_TYPE;
+import static 
org.apache.iotdb.db.metadata.MetadataConstant.MEASUREMENT_MNODE_TYPE;
+import static 
org.apache.iotdb.db.metadata.MetadataConstant.STORAGE_GROUP_ENTITY_MNODE_TYPE;
+import static 
org.apache.iotdb.db.metadata.MetadataConstant.STORAGE_GROUP_MNODE_TYPE;
+
+public class MemMTreeSnapshotUtil {
+
+  private static final Logger logger = 
LoggerFactory.getLogger(MemMTreeSnapshotUtil.class);
+  private static final String SERIALIZE_ERROR_INFO = "Error occurred during 
serializing MemMTree.";
+  private static final String DESERIALIZE_ERROR_INFO =
+      "Error occurred during deserializing MemMTree.";
+
+  private static final byte VERSION = 0;
+
+  public static boolean createSnapshot(File snapshotDir, MemMTreeStore store) {
+    File snapshotTmp =
+        SystemFileFactory.INSTANCE.getFile(snapshotDir, 
MetadataConstant.MTREE_SNAPSHOT_TMP);
+    File snapshot =
+        SystemFileFactory.INSTANCE.getFile(snapshotDir, 
MetadataConstant.MTREE_SNAPSHOT);
+
+    try {
+      try (BufferedOutputStream outputStream =
+          new BufferedOutputStream(new FileOutputStream(snapshotTmp))) {
+        serializeTo(store, outputStream);
+      }
+      if (snapshot.exists() && !snapshot.delete()) {
+        logger.error(
+            "Failed to delete old snapshot {} while creating mtree snapshot.", 
snapshot.getName());
+        return false;
+      }
+      if (!snapshotTmp.renameTo(snapshot)) {
+        logger.error(
+            "Failed to rename {} to {} while creating mtree snapshot.",
+            snapshotTmp.getName(),
+            snapshot.getName());
+        snapshot.delete();
+        return false;
+      }
+
+      return true;
+    } catch (IOException e) {
+      logger.error("Failed to create mtree snapshot due to {}", 
e.getMessage(), e);
+      snapshot.delete();
+      return false;
+    } finally {
+      snapshotTmp.delete();
+    }
+  }
+
+  public static IMNode loadSnapshot(
+      File snapshotDir, Consumer<IMeasurementMNode> measurementProcess) throws 
IOException {
+    File snapshot =
+        SystemFileFactory.INSTANCE.getFile(snapshotDir, 
MetadataConstant.MTREE_SNAPSHOT);
+    try (BufferedInputStream inputStream = new BufferedInputStream(new 
FileInputStream(snapshot))) {
+      return deserializeFrom(inputStream, measurementProcess);
+    }
+  }
+
+  private static void serializeTo(MemMTreeStore store, OutputStream 
outputStream)
+      throws IOException {
+    ReadWriteIOUtils.write(VERSION, outputStream);
+    inorderSerialize(store.getRoot(), store, outputStream);
+  }
+
+  private static void inorderSerialize(IMNode root, MemMTreeStore store, 
OutputStream outputStream)
+      throws IOException {
+    MNodeSerializer serializer = new MNodeSerializer();
+    if (!root.accept(serializer, outputStream)) {
+      throw new IOException(SERIALIZE_ERROR_INFO);
+    }
+
+    Deque<IMNodeIterator> stack = new ArrayDeque<>();
+    stack.push(store.getChildrenIterator(root));
+    IMNode node;
+    IMNodeIterator iterator;
+    while (!stack.isEmpty()) {
+      iterator = stack.peek();
+      if (iterator.hasNext()) {
+        node = iterator.next();
+        if (!node.accept(serializer, outputStream)) {
+          throw new IOException(SERIALIZE_ERROR_INFO);
+        }
+        if (!node.isMeasurement()) {
+          stack.push(store.getChildrenIterator(node));
+        }
+      } else {
+        stack.pop();
+      }
+    }
+  }
+
+  private static IMNode deserializeFrom(
+      InputStream inputStream, Consumer<IMeasurementMNode> measurementProcess) 
throws IOException {
+    byte version = ReadWriteIOUtils.readByte(inputStream);
+    return inorderDeserialize(inputStream, measurementProcess);
+  }
+
+  private static IMNode inorderDeserialize(
+      InputStream inputStream, Consumer<IMeasurementMNode> measurementProcess) 
throws IOException {
+    MNodeDeserializer deserializer = new MNodeDeserializer();
+    Deque<IMNode> ancestors = new ArrayDeque<>();
+    Deque<Integer> restChildrenNum = new ArrayDeque<>();
+    deserializeMNode(ancestors, restChildrenNum, deserializer, inputStream, 
measurementProcess);
+    int childrenNum;
+    IMNode root = ancestors.peek();
+    while (!ancestors.isEmpty()) {
+      childrenNum = restChildrenNum.pop();
+      if (childrenNum == 0) {
+        ancestors.pop();
+      } else {
+        restChildrenNum.push(childrenNum - 1);
+        deserializeMNode(ancestors, restChildrenNum, deserializer, 
inputStream, measurementProcess);
+      }
+    }
+    return root;
+  }
+
+  private static void deserializeMNode(
+      Deque<IMNode> ancestors,
+      Deque<Integer> restChildrenNum,
+      MNodeDeserializer deserializer,
+      InputStream inputStream,
+      Consumer<IMeasurementMNode> measurementProcess)
+      throws IOException {
+    byte type = ReadWriteIOUtils.readByte(inputStream);
+    IMNode node;
+    int childrenNum;
+    switch (type) {
+      case INTERNAL_MNODE_TYPE:
+        childrenNum = ReadWriteIOUtils.readInt(inputStream);
+        node = deserializer.deserializeInternalMNode(inputStream);
+        break;
+      case STORAGE_GROUP_MNODE_TYPE:
+        childrenNum = ReadWriteIOUtils.readInt(inputStream);
+        node = deserializer.deserializeStorageGroupMNode(inputStream);
+        break;
+      case ENTITY_MNODE_TYPE:
+        childrenNum = ReadWriteIOUtils.readInt(inputStream);
+        node = deserializer.deserializeEntityMNode(inputStream);
+        break;
+      case STORAGE_GROUP_ENTITY_MNODE_TYPE:
+        childrenNum = ReadWriteIOUtils.readInt(inputStream);
+        node = deserializer.deserializeStorageGroupEntityMNode(inputStream);
+        break;
+      case MEASUREMENT_MNODE_TYPE:
+        childrenNum = 0;
+        node = deserializer.deserializeMeasurementMNode(inputStream);
+        measurementProcess.accept(node.getAsMeasurementMNode());
+        break;
+      default:
+        throw new IOException("Unrecognized MNode type " + type);
+    }
+
+    if (!ancestors.isEmpty()) {
+      node.setParent(ancestors.peek());
+      ancestors.peek().addChild(node);
+    }
+
+    if (childrenNum > 0) {
+      ancestors.push(node);
+      restChildrenNum.push(childrenNum);
+    }
+  }
+
+  private static class MNodeSerializer extends MNodeVisitor<Boolean, 
OutputStream> {
+
+    @Override
+    public Boolean visitInternalMNode(InternalMNode node, OutputStream 
outputStream) {
+      try {
+        ReadWriteIOUtils.write(INTERNAL_MNODE_TYPE, outputStream);
+        serializeInternalBasicInfo(node, outputStream);
+        return true;
+      } catch (IOException e) {
+        logger.error(SERIALIZE_ERROR_INFO, e);
+        return false;
+      }
+    }
+
+    @Override
+    public Boolean visitStorageGroupMNode(StorageGroupMNode node, OutputStream 
outputStream) {
+      try {
+        ReadWriteIOUtils.write(STORAGE_GROUP_MNODE_TYPE, outputStream);
+        serializeInternalBasicInfo(node, outputStream);
+        // storage group node in schemaRegion doesn't store any storage group 
schema
+        return true;
+      } catch (IOException e) {
+        logger.error(SERIALIZE_ERROR_INFO, e);
+        return false;
+      }
+    }
+
+    @Override
+    public Boolean visitStorageGroupEntityMNode(
+        StorageGroupEntityMNode node, OutputStream outputStream) {
+      try {
+        ReadWriteIOUtils.write(STORAGE_GROUP_ENTITY_MNODE_TYPE, outputStream);
+        serializeInternalBasicInfo(node, outputStream);
+        ReadWriteIOUtils.write(node.isAligned(), outputStream);
+        // storage group node in schemaRegion doesn't store any storage group 
schema
+        return true;
+      } catch (IOException e) {
+        logger.error(SERIALIZE_ERROR_INFO, e);
+        return false;
+      }
+    }
+
+    @Override
+    public Boolean visitEntityMNode(EntityMNode node, OutputStream 
outputStream) {
+      try {
+        ReadWriteIOUtils.write(ENTITY_MNODE_TYPE, outputStream);
+        serializeInternalBasicInfo(node, outputStream);
+        ReadWriteIOUtils.write(node.isAligned(), outputStream);
+        return true;
+      } catch (IOException e) {
+        logger.error(SERIALIZE_ERROR_INFO, e);
+        return false;
+      }
+    }
+
+    @Override
+    public Boolean visitMeasurementMNode(MeasurementMNode node, OutputStream 
outputStream) {
+      try {
+        ReadWriteIOUtils.write(MEASUREMENT_MNODE_TYPE, outputStream);
+        ReadWriteIOUtils.write(node.getName(), outputStream);
+        node.getSchema().serializeTo(outputStream);
+        ReadWriteIOUtils.write(node.getAlias(), outputStream);
+        ReadWriteIOUtils.write(node.getOffset(), outputStream);
+        return true;
+      } catch (IOException e) {
+        logger.error(SERIALIZE_ERROR_INFO, e);
+        return false;
+      }
+    }
+
+    private void serializeInternalBasicInfo(InternalMNode node, OutputStream 
outputStream)
+        throws IOException {
+      ReadWriteIOUtils.write(node.getChildren().size(), outputStream);
+      ReadWriteIOUtils.write(node.getName(), outputStream);
+      ReadWriteIOUtils.write(-1, outputStream); // todo template id
+      ReadWriteIOUtils.write(node.isUseTemplate(), outputStream);
+    }
+  }
+
+  private static class MNodeDeserializer {
+
+    public InternalMNode deserializeInternalMNode(InputStream inputStream) 
throws IOException {
+      String name = ReadWriteIOUtils.readString(inputStream);
+      InternalMNode node = new InternalMNode(null, name);
+      deserializeInternalBasicInfo(node, inputStream);
+      return node;
+    }
+
+    public StorageGroupMNode deserializeStorageGroupMNode(InputStream 
inputStream)
+        throws IOException {
+      String name = ReadWriteIOUtils.readString(inputStream);
+      StorageGroupMNode node = new StorageGroupMNode(null, name);
+      deserializeInternalBasicInfo(node, inputStream);
+      return node;
+    }
+
+    public StorageGroupEntityMNode 
deserializeStorageGroupEntityMNode(InputStream inputStream)
+        throws IOException {
+      String name = ReadWriteIOUtils.readString(inputStream);
+      StorageGroupEntityMNode node = new StorageGroupEntityMNode(null, name, 
0);
+      deserializeInternalBasicInfo(node, inputStream);
+      node.setAligned(ReadWriteIOUtils.readBool(inputStream));
+      return node;
+    }
+
+    public EntityMNode deserializeEntityMNode(InputStream inputStream) throws 
IOException {
+      String name = ReadWriteIOUtils.readString(inputStream);
+      EntityMNode node = new EntityMNode(null, name);
+      deserializeInternalBasicInfo(node, inputStream);
+      node.setAligned(ReadWriteIOUtils.readBool(inputStream));
+      return node;
+    }
+
+    public MeasurementMNode deserializeMeasurementMNode(InputStream 
inputStream)
+        throws IOException {
+      String name = ReadWriteIOUtils.readString(inputStream);
+      MeasurementSchema schema = 
MeasurementSchema.deserializeFrom(inputStream);
+      String alias = ReadWriteIOUtils.readString(inputStream);
+      long tagOffset = ReadWriteIOUtils.readLong(inputStream);
+      MeasurementMNode node = new MeasurementMNode(null, name, schema, alias);
+      node.setOffset(tagOffset);
+      return node;
+    }
+
+    private void deserializeInternalBasicInfo(InternalMNode node, InputStream 
inputStream)
+        throws IOException {
+      int templateId = ReadWriteIOUtils.readInt(inputStream);
+      node.setUseTemplate(ReadWriteIOUtils.readBool(inputStream));
+    }
+  }
+}
diff --git 
a/server/src/main/java/org/apache/iotdb/db/metadata/mtree/store/CachedMTreeStore.java
 
b/server/src/main/java/org/apache/iotdb/db/metadata/mtree/store/CachedMTreeStore.java
index 3289e4d674..7895fa53ca 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/metadata/mtree/store/CachedMTreeStore.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/metadata/mtree/store/CachedMTreeStore.java
@@ -40,6 +40,7 @@ import 
org.apache.iotdb.db.metadata.mtree.store.disk.schemafile.SchemaFile;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.io.File;
 import java.io.IOException;
 import java.util.Iterator;
 import java.util.List;
@@ -380,6 +381,12 @@ public class CachedMTreeStore implements IMTreeStore {
     }
   }
 
+  @Override
+  public boolean createSnapshot(File snapshotDir) {
+    // todo implement snapshot for schema file mode
+    return false;
+  }
+
   private void ensureMemoryStatus() {
     if (memManager.isExceedFlushThreshold()) {
       if (!hasReleaseTask) {
diff --git 
a/server/src/main/java/org/apache/iotdb/db/metadata/mtree/store/IMTreeStore.java
 
b/server/src/main/java/org/apache/iotdb/db/metadata/mtree/store/IMTreeStore.java
index 7331ed558c..8cd34035b3 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/metadata/mtree/store/IMTreeStore.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/metadata/mtree/store/IMTreeStore.java
@@ -24,6 +24,8 @@ import org.apache.iotdb.db.metadata.mnode.IMNode;
 import org.apache.iotdb.db.metadata.mnode.IMeasurementMNode;
 import org.apache.iotdb.db.metadata.mnode.iterator.IMNodeIterator;
 
+import java.io.File;
+
 /**
  * This interface defines the basic access methods of an MTreeStore.
  *
@@ -58,4 +60,6 @@ public interface IMTreeStore {
   void unPinPath(IMNode node);
 
   void clear();
+
+  boolean createSnapshot(File snapshotDir);
 }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/metadata/mtree/store/MemMTreeStore.java
 
b/server/src/main/java/org/apache/iotdb/db/metadata/mtree/store/MemMTreeStore.java
index 9cf7ee1308..6c6bd68ee5 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/metadata/mtree/store/MemMTreeStore.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/metadata/mtree/store/MemMTreeStore.java
@@ -31,9 +31,13 @@ import 
org.apache.iotdb.db.metadata.mnode.estimator.BasicMNodSizeEstimator;
 import org.apache.iotdb.db.metadata.mnode.estimator.IMNodeSizeEstimator;
 import org.apache.iotdb.db.metadata.mnode.iterator.IMNodeIterator;
 import org.apache.iotdb.db.metadata.mnode.iterator.MNodeIterator;
+import org.apache.iotdb.db.metadata.mtree.snapshot.MemMTreeSnapshotUtil;
 import org.apache.iotdb.db.metadata.rescon.MemoryStatistics;
 
+import java.io.File;
+import java.io.IOException;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.Consumer;
 
 /** This is a memory-based implementation of IMTreeStore. All MNodes are 
stored in memory. */
 public class MemMTreeStore implements IMTreeStore {
@@ -56,6 +60,10 @@ public class MemMTreeStore implements IMTreeStore {
     }
   }
 
+  private MemMTreeStore(IMNode root) {
+    this.root = root;
+  }
+
   @Override
   public IMNode getRoot() {
     return root;
@@ -158,6 +166,16 @@ public class MemMTreeStore implements IMTreeStore {
     localMemoryUsage.set(0);
   }
 
+  @Override
+  public boolean createSnapshot(File snapshotDir) {
+    return MemMTreeSnapshotUtil.createSnapshot(snapshotDir, this);
+  }
+
+  public static MemMTreeStore loadFromSnapshot(
+      File snapshotDir, Consumer<IMeasurementMNode> measurementProcess) throws 
IOException {
+    return new MemMTreeStore(MemMTreeSnapshotUtil.loadSnapshot(snapshotDir, 
measurementProcess));
+  }
+
   private void requestMemory(int size) {
     memoryStatistics.requestMemory(size);
     localMemoryUsage.getAndUpdate(v -> v += size);
diff --git 
a/server/src/main/java/org/apache/iotdb/db/metadata/schemaregion/SchemaEngine.java
 
b/server/src/main/java/org/apache/iotdb/db/metadata/schemaregion/SchemaEngine.java
index 30edd2bc31..584f7b78b3 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/metadata/schemaregion/SchemaEngine.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/metadata/schemaregion/SchemaEngine.java
@@ -26,6 +26,7 @@ import 
org.apache.iotdb.commons.exception.IllegalPathException;
 import org.apache.iotdb.commons.exception.MetadataException;
 import org.apache.iotdb.commons.path.PartialPath;
 import org.apache.iotdb.commons.utils.FileUtils;
+import org.apache.iotdb.consensus.ConsensusFactory;
 import org.apache.iotdb.db.conf.IoTDBConfig;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.exception.metadata.StorageGroupAlreadySetException;
@@ -105,7 +106,11 @@ public class SchemaEngine {
 
     Map<PartialPath, List<SchemaRegionId>> schemaRegionInfo = 
initSchemaRegion();
 
-    if (config.getSyncMlogPeriodInMs() != 0) {
+    if (!(config.isClusterMode()
+            && config
+                .getSchemaRegionConsensusProtocolClass()
+                .equals(ConsensusFactory.RatisConsensus))
+        && config.getSyncMlogPeriodInMs() != 0) {
       timedForceMLogThread =
           IoTDBThreadPoolFactory.newSingleThreadScheduledExecutor(
               "SchemaEngine-TimedForceMLog-Thread");
diff --git 
a/server/src/main/java/org/apache/iotdb/db/metadata/schemaregion/SchemaRegionMemoryImpl.java
 
b/server/src/main/java/org/apache/iotdb/db/metadata/schemaregion/SchemaRegionMemoryImpl.java
index 84815a9383..8af29746f8 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/metadata/schemaregion/SchemaRegionMemoryImpl.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/metadata/schemaregion/SchemaRegionMemoryImpl.java
@@ -22,6 +22,7 @@ import org.apache.iotdb.commons.consensus.SchemaRegionId;
 import org.apache.iotdb.commons.exception.MetadataException;
 import org.apache.iotdb.commons.file.SystemFileFactory;
 import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.consensus.ConsensusFactory;
 import org.apache.iotdb.db.conf.IoTDBConfig;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.engine.StorageEngine;
@@ -84,7 +85,6 @@ import 
org.apache.iotdb.tsfile.write.schema.IMeasurementSchema;
 
 import com.github.benmanes.caffeine.cache.Caffeine;
 import com.github.benmanes.caffeine.cache.LoadingCache;
-import org.apache.commons.io.FileUtils;
 import org.checkerframework.checker.nullness.qual.NonNull;
 import org.checkerframework.checker.nullness.qual.Nullable;
 import org.slf4j.Logger;
@@ -142,7 +142,7 @@ import static 
org.apache.iotdb.tsfile.common.constant.TsFileConstant.PATH_SEPARA
 @SuppressWarnings("java:S1135") // ignore todos
 public class SchemaRegionMemoryImpl implements ISchemaRegion {
 
-  private static final Logger logger = 
LoggerFactory.getLogger(SchemaRegionSchemaFileImpl.class);
+  private static final Logger logger = 
LoggerFactory.getLogger(SchemaRegionMemoryImpl.class);
 
   protected static IoTDBConfig config = 
IoTDBDescriptor.getInstance().getConfig();
 
@@ -153,9 +153,8 @@ public class SchemaRegionMemoryImpl implements 
ISchemaRegion {
   private String storageGroupFullPath;
   private SchemaRegionId schemaRegionId;
 
-  // the log file seriesPath
-  private String logFilePath;
-  private File logFile;
+  // the log file writer
+  private boolean usingMLog = true;
   private MLogWriter logWriter;
 
   private TimeseriesStatistics timeseriesStatistics = 
TimeseriesStatistics.getInstance();
@@ -199,6 +198,36 @@ public class SchemaRegionMemoryImpl implements 
ISchemaRegion {
       return;
     }
 
+    initDir();
+
+    try {
+      // do not write log when recover
+      isRecovering = true;
+
+      tagManager = new TagManager(schemaRegionDirPath);
+      mtree = new MTreeBelowSGMemoryImpl(storageGroupMNode, 
schemaRegionId.getId());
+
+      if (!(config.isClusterMode()
+          && config
+              .getSchemaRegionConsensusProtocolClass()
+              .equals(ConsensusFactory.RatisConsensus))) {
+        usingMLog = true;
+        initMLog();
+      } else {
+        usingMLog = false;
+      }
+
+      isRecovering = false;
+    } catch (IOException e) {
+      logger.error(
+          "Cannot recover all schema info from {}, we try to recover as 
possible as we can",
+          schemaRegionDirPath,
+          e);
+    }
+    initialized = true;
+  }
+
+  private void initDir() throws SchemaDirCreationFailureException {
     String sgDirPath = config.getSchemaDir() + File.separator + 
storageGroupFullPath;
     File sgSchemaFolder = SystemFileFactory.INSTANCE.getFile(sgDirPath);
     if (!sgSchemaFolder.exists()) {
@@ -229,39 +258,31 @@ public class SchemaRegionMemoryImpl implements 
ISchemaRegion {
         }
       }
     }
-    logFilePath = schemaRegionDirPath + File.separator + 
MetadataConstant.METADATA_LOG;
-
-    logFile = SystemFileFactory.INSTANCE.getFile(logFilePath);
-
-    try {
-      // do not write log when recover
-      isRecovering = true;
+  }
 
-      tagManager = new TagManager(schemaRegionDirPath);
-      mtree = new MTreeBelowSGMemoryImpl(storageGroupMNode, 
schemaRegionId.getId());
+  private void initMLog() throws IOException {
+    int lineNumber = initFromLog();
 
-      int lineNumber = initFromLog(logFile);
+    logWriter = new MLogWriter(schemaRegionDirPath, 
MetadataConstant.METADATA_LOG);
+    logWriter.setLogNum(lineNumber);
+  }
 
-      logWriter = new MLogWriter(schemaRegionDirPath, 
MetadataConstant.METADATA_LOG);
-      logWriter.setLogNum(lineNumber);
-      isRecovering = false;
-    } catch (IOException e) {
-      logger.error(
-          "Cannot recover all MTree from {} file, we try to recover as 
possible as we can",
-          storageGroupFullPath,
-          e);
+  public void writeToMLog(PhysicalPlan plan) throws IOException {
+    if (usingMLog && !isRecovering) {
+      logWriter.putLog(plan);
     }
-    initialized = true;
   }
 
   public void forceMlog() {
     if (!initialized) {
       return;
     }
-    try {
-      logWriter.force();
-    } catch (IOException e) {
-      logger.error("Cannot force {} mlog to the schema region", 
schemaRegionId, e);
+    if (usingMLog) {
+      try {
+        logWriter.force();
+      } catch (IOException e) {
+        logger.error("Cannot force {} mlog to the schema region", 
schemaRegionId, e);
+      }
     }
   }
 
@@ -271,7 +292,11 @@ public class SchemaRegionMemoryImpl implements 
ISchemaRegion {
    * @return line number of the logFile
    */
   @SuppressWarnings("squid:S3776")
-  private int initFromLog(File logFile) throws IOException {
+  private int initFromLog() throws IOException {
+    File logFile =
+        SystemFileFactory.INSTANCE.getFile(
+            schemaRegionDirPath + File.separator + 
MetadataConstant.METADATA_LOG);
+
     long time = System.currentTimeMillis();
     // init the metadata from the operation log
     if (logFile.exists()) {
@@ -413,76 +438,104 @@ public class SchemaRegionMemoryImpl implements 
ISchemaRegion {
     SchemaRegionUtils.deleteSchemaRegionFolder(schemaRegionDirPath, logger);
   }
 
+  // currently, this method is only used for cluster-ratis mode
   @Override
   public synchronized boolean createSnapshot(File snapshotDir) {
-    File mLogSnapshotTmp =
-        SystemFileFactory.INSTANCE.getFile(snapshotDir, 
MetadataConstant.METADATA_LOG_SNAPSHOT_TMP);
-    File mLogSnapshot =
-        SystemFileFactory.INSTANCE.getFile(snapshotDir, 
MetadataConstant.METADATA_LOG_SNAPSHOT);
-
-    try {
-      logWriter.copyTo(mLogSnapshotTmp);
-      if (mLogSnapshot.exists() && !mLogSnapshot.delete()) {
-        logger.error(
-            "Failed to delete old snapshot file {} while creating snapshot for 
schemaRegion {}.",
-            mLogSnapshot.getName(),
-            schemaRegionId);
-        return false;
-      }
-
-      if (!mLogSnapshotTmp.renameTo(mLogSnapshot)) {
-        logger.error(
-            "Failed to rename {} to {} while creating snapshot for 
schemaRegion {}.",
-            mLogSnapshotTmp.getName(),
-            mLogSnapshot.getName(),
-            schemaRegionId);
-        mLogSnapshot.delete();
-        return false;
-      }
-
-      return tagManager.createSnapshot(snapshotDir);
-    } catch (IOException e) {
-      logger.error(
-          "Failed to create snapshot for schemaRegion {} due to {}",
-          schemaRegionId,
-          e.getMessage(),
-          e);
-      mLogSnapshot.delete();
-      return false;
-    } finally {
-      mLogSnapshotTmp.delete();
-    }
-  }
-
+    logger.info("Start create snapshot of schemaRegion {}", schemaRegionId);
+    boolean isSuccess = true;
+    long startTime = System.currentTimeMillis();
+
+    long mtreeSnapshotStartTime = System.currentTimeMillis();
+    isSuccess = isSuccess && mtree.createSnapshot(snapshotDir);
+    logger.info(
+        "MTree snapshot creation of schemaRegion {} costs {}ms.",
+        schemaRegionId,
+        System.currentTimeMillis() - mtreeSnapshotStartTime);
+
+    long tagSnapshotStartTime = System.currentTimeMillis();
+    isSuccess = isSuccess && tagManager.createSnapshot(snapshotDir);
+    logger.info(
+        "Tag snapshot creation of schemaRegion {} costs {}ms.",
+        schemaRegionId,
+        System.currentTimeMillis() - tagSnapshotStartTime);
+
+    logger.info(
+        "Snapshot creation of schemaRegion {} costs {}ms.",
+        schemaRegionId,
+        System.currentTimeMillis() - startTime);
+    logger.info("Successfully create snapshot of schemaRegion {}", 
schemaRegionId);
+
+    return isSuccess;
+  }
+
+  // currently, this method is only used for cluster-ratis mode
   @Override
   public void loadSnapshot(File latestSnapshotRootDir) {
-    File mLogSnapshot =
-        SystemFileFactory.INSTANCE.getFile(
-            latestSnapshotRootDir, MetadataConstant.METADATA_LOG_SNAPSHOT);
-    File tagSnapshot =
-        SystemFileFactory.INSTANCE.getFile(
-            latestSnapshotRootDir, MetadataConstant.TAG_LOG_SNAPSHOT);
-
     clear();
 
-    File mLog =
-        SystemFileFactory.INSTANCE.getFile(schemaRegionDirPath, 
MetadataConstant.METADATA_LOG);
-    File tagFile =
-        SystemFileFactory.INSTANCE.getFile(schemaRegionDirPath, 
MetadataConstant.TAG_LOG);
-    mLog.delete();
-    tagFile.delete();
+    logger.info("Start loading snapshot of schemaRegion {}", schemaRegionId);
+    long startTime = System.currentTimeMillis();
 
     try {
-      FileUtils.copyFile(mLogSnapshot, mLog);
-      FileUtils.copyFile(tagSnapshot, tagFile);
+      usingMLog = false;
+
+      isRecovering = true;
+
+      long tagSnapshotStartTime = System.currentTimeMillis();
+      tagManager = TagManager.loadFromSnapshot(latestSnapshotRootDir, 
schemaRegionDirPath);
+      logger.info(
+          "Tag snapshot loading of schemaRegion {} costs {}ms.",
+          schemaRegionId,
+          System.currentTimeMillis() - tagSnapshotStartTime);
+
+      long mtreeSnapshotStartTime = System.currentTimeMillis();
+      mtree =
+          MTreeBelowSGMemoryImpl.loadFromSnapshot(
+              latestSnapshotRootDir,
+              storageGroupMNode,
+              schemaRegionId.getId(),
+              measurementMNode -> {
+                if (measurementMNode.getOffset() == -1) {
+                  return;
+                }
+                try {
+                  tagManager.recoverIndex(measurementMNode.getOffset(), 
measurementMNode);
+                } catch (IOException e) {
+                  logger.error(
+                      "Failed to recover tagIndex for {} in schemaRegion {}.",
+                      storageGroupFullPath + PATH_SEPARATOR + 
measurementMNode.getFullPath(),
+                      schemaRegionId);
+                }
+              });
+      logger.info(
+          "MTree snapshot loading of schemaRegion {} costs {}ms.",
+          schemaRegionId,
+          System.currentTimeMillis() - mtreeSnapshotStartTime);
 
-      init();
-    } catch (IOException | MetadataException e) {
+      isRecovering = false;
+      initialized = true;
+
+      logger.info(
+          "Snapshot loading of schemaRegion {} costs {}ms.",
+          schemaRegionId,
+          System.currentTimeMillis() - startTime);
+      logger.info("Successfully load snapshot of schemaRegion {}", 
schemaRegionId);
+    } catch (IOException e) {
       logger.error(
-          "Failed to load snapshot for schemaRegion {}  ue to {}",
+          "Failed to load snapshot for schemaRegion {}  due to {}. Use empty 
schemaRegion",
           schemaRegionId,
           e.getMessage(),
           e);
+      try {
+        initialized = false;
+        isRecovering = true;
+        init();
+      } catch (MetadataException metadataException) {
+        logger.error(
+            "Error occurred during initializing schemaRegion {}",
+            schemaRegionId,
+            metadataException);
+      }
     }
   }
 
@@ -541,7 +594,7 @@ public class SchemaRegionMemoryImpl implements 
ISchemaRegion {
           offset = tagManager.writeTagFile(plan.getTags(), 
plan.getAttributes());
         }
         plan.setTagOffset(offset);
-        logWriter.createTimeseries(plan);
+        writeToMLog(plan);
         if (syncManager.isEnableSync()) {
           syncManager.syncMetadataPlan(plan);
         }
@@ -675,7 +728,7 @@ public class SchemaRegionMemoryImpl implements 
ISchemaRegion {
           }
         }
         plan.setTagOffsets(tagOffsets);
-        logWriter.createAlignedTimeseries(plan);
+        writeToMLog(plan);
         if (syncManager.isEnableSync()) {
           syncManager.syncMetadataPlan(plan);
         }
@@ -744,7 +797,7 @@ public class SchemaRegionMemoryImpl implements 
ISchemaRegion {
           
StorageEngine.getInstance().deleteAllDataFilesInOneStorageGroup(emptyStorageGroup);
         }
         deleteTimeSeriesPlan.setDeletePathList(Collections.singletonList(p));
-        logWriter.deleteTimeseries(deleteTimeSeriesPlan);
+        writeToMLog(deleteTimeSeriesPlan);
         if (syncManager.isEnableSync()) {
           syncManager.syncMetadataPlan(deleteTimeSeriesPlan);
         }
@@ -808,20 +861,16 @@ public class SchemaRegionMemoryImpl implements 
ISchemaRegion {
     }
 
     node = mtree.getDeviceNodeWithAutoCreating(path);
-    if (!isRecovering) {
-      logWriter.autoCreateDeviceMNode(new 
AutoCreateDeviceMNodePlan(node.getPartialPath()));
-    }
+    writeToMLog(new AutoCreateDeviceMNodePlan(node.getPartialPath()));
     return node;
   }
 
   public void autoCreateDeviceMNode(AutoCreateDeviceMNodePlan plan) throws 
MetadataException {
     mtree.getDeviceNodeWithAutoCreating(plan.getPath());
-    if (!isRecovering) {
-      try {
-        logWriter.autoCreateDeviceMNode(plan);
-      } catch (IOException e) {
-        throw new MetadataException(e);
-      }
+    try {
+      writeToMLog(plan);
+    } catch (IOException e) {
+      throw new MetadataException(e);
     }
   }
   // endregion
@@ -1240,7 +1289,6 @@ public class SchemaRegionMemoryImpl implements 
ISchemaRegion {
     measurementMNode.setOffset(offset);
 
     if (isRecovering) {
-
       try {
         tagManager.recoverIndex(offset, measurementMNode);
       } catch (IOException e) {
@@ -1258,9 +1306,7 @@ public class SchemaRegionMemoryImpl implements 
ISchemaRegion {
     mtree.setAlias(leafMNode, alias);
 
     try {
-      if (!isRecovering) {
-        logWriter.changeAlias(path, alias);
-      }
+      writeToMLog(new ChangeAliasPlan(path, alias));
     } catch (IOException e) {
       throw new MetadataException(e);
     }
@@ -1294,7 +1340,7 @@ public class SchemaRegionMemoryImpl implements 
ISchemaRegion {
     // no tag or attribute, we need to add a new record in log
     if (leafMNode.getOffset() < 0) {
       long offset = tagManager.writeTagFile(tagsMap, attributesMap);
-      logWriter.changeOffset(fullPath, offset);
+      writeToMLog(new ChangeTagOffsetPlan(fullPath, offset));
       leafMNode.setOffset(offset);
       // update inverted Index map
       if (tagsMap != null && !tagsMap.isEmpty()) {
@@ -1320,7 +1366,7 @@ public class SchemaRegionMemoryImpl implements 
ISchemaRegion {
 
       mtree.setAlias(leafMNode, alias);
       // persist to WAL
-      logWriter.changeAlias(fullPath, alias);
+      writeToMLog(new ChangeAliasPlan(fullPath, alias));
     }
   }
 
@@ -1337,7 +1383,7 @@ public class SchemaRegionMemoryImpl implements 
ISchemaRegion {
     // no tag or attribute, we need to add a new record in log
     if (leafMNode.getOffset() < 0) {
       long offset = tagManager.writeTagFile(Collections.emptyMap(), 
attributesMap);
-      logWriter.changeOffset(fullPath, offset);
+      writeToMLog(new ChangeTagOffsetPlan(fullPath, offset));
       leafMNode.setOffset(offset);
       return;
     }
@@ -1357,7 +1403,7 @@ public class SchemaRegionMemoryImpl implements 
ISchemaRegion {
     // no tag or attribute, we need to add a new record in log
     if (leafMNode.getOffset() < 0) {
       long offset = tagManager.writeTagFile(tagsMap, Collections.emptyMap());
-      logWriter.changeOffset(fullPath, offset);
+      writeToMLog(new ChangeTagOffsetPlan(fullPath, offset));
       leafMNode.setOffset(offset);
       // update inverted Index map
       tagManager.addIndex(tagsMap, leafMNode);
@@ -1683,9 +1729,7 @@ public class SchemaRegionMemoryImpl implements 
ISchemaRegion {
           .markSchemaRegion(template, storageGroupFullPath, schemaRegionId);
 
       // write wal
-      if (!isRecovering) {
-        logWriter.setSchemaTemplate(plan);
-      }
+      writeToMLog(plan);
     } catch (IOException e) {
       throw new MetadataException(e);
     }
@@ -1709,9 +1753,7 @@ public class SchemaRegionMemoryImpl implements 
ISchemaRegion {
       TemplateManager.getInstance()
           .unmarkSchemaRegion(template, storageGroupFullPath, schemaRegionId);
       // write wal
-      if (!isRecovering) {
-        logWriter.unsetSchemaTemplate(plan);
-      }
+      writeToMLog(plan);
     } catch (IOException e) {
       throw new MetadataException(e);
     }
@@ -1766,12 +1808,10 @@ public class SchemaRegionMemoryImpl implements 
ISchemaRegion {
     if (node != mountedMNode) {
       mNodeCache.invalidate(mountedMNode.getPartialPath());
     }
-    if (!isRecovering) {
-      try {
-        logWriter.setUsingSchemaTemplate(node.getPartialPath());
-      } catch (IOException e) {
-        throw new MetadataException(e);
-      }
+    try {
+      writeToMLog(new ActivateTemplatePlan(node.getPartialPath()));
+    } catch (IOException e) {
+      throw new MetadataException(e);
     }
     return mountedMNode;
   }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/metadata/tag/TagManager.java 
b/server/src/main/java/org/apache/iotdb/db/metadata/tag/TagManager.java
index 4f081c77de..4dd2295431 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/tag/TagManager.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/tag/TagManager.java
@@ -36,6 +36,7 @@ import org.apache.iotdb.db.query.context.QueryContext;
 import org.apache.iotdb.db.query.control.QueryResourceManager;
 import org.apache.iotdb.tsfile.utils.Pair;
 
+import org.apache.commons.io.FileUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -107,6 +108,24 @@ public class TagManager {
     }
   }
 
+  public static TagManager loadFromSnapshot(File snapshotDir, String 
sgSchemaDirPath)
+      throws IOException {
+    File tagSnapshot =
+        SystemFileFactory.INSTANCE.getFile(snapshotDir, 
MetadataConstant.TAG_LOG_SNAPSHOT);
+    File tagFile = SystemFileFactory.INSTANCE.getFile(sgSchemaDirPath, 
MetadataConstant.TAG_LOG);
+    if (tagFile.exists()) {
+      tagFile.delete();
+    }
+
+    try {
+      FileUtils.copyFile(tagSnapshot, tagFile);
+      return new TagManager(sgSchemaDirPath);
+    } catch (IOException e) {
+      tagFile.delete();
+      throw e;
+    }
+  }
+
   public boolean recoverIndex(long offset, IMeasurementMNode measurementMNode) 
throws IOException {
     Map<String, String> tags = 
tagLogFile.readTag(config.getTagAttributeTotalSize(), offset);
     if (tags == null || tags.isEmpty()) {
diff --git 
a/server/src/main/java/org/apache/iotdb/db/metadata/upgrade/MetadataUpgrader.java
 
b/server/src/main/java/org/apache/iotdb/db/metadata/upgrade/MetadataUpgrader.java
index 599ddfb850..c17d8f7ac9 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/metadata/upgrade/MetadataUpgrader.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/metadata/upgrade/MetadataUpgrader.java
@@ -80,9 +80,9 @@ public class MetadataUpgrader {
   private File tagFile = new File(tagFilePath);
 
   private String mtreeSnapshotPath =
-      schemaDirPath + File.separator + MetadataConstant.MTREE_SNAPSHOT;
+      schemaDirPath + File.separator + 
MetadataConstant.MTREE_SNAPSHOT_OLD_VERSION;
   private String mtreeSnapshotTmpPath =
-      schemaDirPath + File.separator + MetadataConstant.MTREE_SNAPSHOT_TMP;
+      schemaDirPath + File.separator + 
MetadataConstant.MTREE_SNAPSHOT_TMP_OLDVERSION;
   private File snapshotFile = new File(mtreeSnapshotPath);
   private File snapshotTmpFile = new File(mtreeSnapshotTmpPath);
 
diff --git 
a/server/src/test/java/org/apache/iotdb/db/metadata/schemaRegion/SchemaRegionTest.java
 
b/server/src/test/java/org/apache/iotdb/db/metadata/schemaRegion/SchemaRegionTest.java
index a8c8498c8b..541ac96513 100644
--- 
a/server/src/test/java/org/apache/iotdb/db/metadata/schemaRegion/SchemaRegionTest.java
+++ 
b/server/src/test/java/org/apache/iotdb/db/metadata/schemaRegion/SchemaRegionTest.java
@@ -20,9 +20,12 @@
 package org.apache.iotdb.db.metadata.schemaRegion;
 
 import org.apache.iotdb.commons.consensus.SchemaRegionId;
+import org.apache.iotdb.commons.file.SystemFileFactory;
 import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.consensus.ConsensusFactory;
 import org.apache.iotdb.db.conf.IoTDBConfig;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
+import org.apache.iotdb.db.metadata.MetadataConstant;
 import org.apache.iotdb.db.metadata.schemaregion.ISchemaRegion;
 import org.apache.iotdb.db.metadata.schemaregion.SchemaEngine;
 import org.apache.iotdb.db.qp.physical.sys.CreateTimeSeriesPlan;
@@ -37,6 +40,7 @@ import org.apache.iotdb.tsfile.utils.Pair;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 
 import java.io.File;
@@ -49,23 +53,49 @@ public class SchemaRegionTest {
   SchemaEngine schemaEngine = SchemaEngine.getInstance();
   IoTDBConfig config = IoTDBDescriptor.getInstance().getConfig();
 
+  boolean isMppMode;
+  boolean isClusterMode;
+  String schemaRegionConsensusProtocolClass;
+  long schemaMemory;
+
   @Before
   public void setUp() {
+    isMppMode = config.isMppMode();
+    isClusterMode = config.isClusterMode();
+    schemaRegionConsensusProtocolClass = 
config.getSchemaRegionConsensusProtocolClass();
+    schemaMemory = config.getAllocateMemoryForSchema();
+
+    config.setMppMode(true);
+    config.setClusterMode(true);
+    
config.setSchemaRegionConsensusProtocolClass(ConsensusFactory.RatisConsensus);
+    config.setAllocateMemoryForSchema(1024 * 1024 * 1024);
     EnvironmentUtils.envSetUp();
   }
 
   @After
   public void tearDown() throws Exception {
     EnvironmentUtils.cleanEnv();
+    config.setMppMode(isMppMode);
+    config.setClusterMode(isClusterMode);
+    
config.setSchemaRegionConsensusProtocolClass(schemaRegionConsensusProtocolClass);
+    config.setAllocateMemoryForSchema(schemaMemory);
   }
 
   @Test
-  public void testSnapshot() throws Exception {
+  public void testRatisModeSnapshot() throws Exception {
     PartialPath storageGroup = new PartialPath("root.sg");
     SchemaRegionId schemaRegionId = new SchemaRegionId(0);
     schemaEngine.createSchemaRegion(storageGroup, schemaRegionId);
     ISchemaRegion schemaRegion = 
SchemaEngine.getInstance().getSchemaRegion(schemaRegionId);
 
+    File mLogFile =
+        SystemFileFactory.INSTANCE.getFile(
+            schemaRegion.getStorageGroupFullPath()
+                + File.separator
+                + schemaRegion.getSchemaRegionId().getId(),
+            MetadataConstant.METADATA_LOG);
+    Assert.assertFalse(mLogFile.exists());
+
     Map<String, String> tags = new HashMap<>();
     tags.put("tag-key", "tag-value");
     schemaRegion.createTimeseries(
@@ -81,6 +111,7 @@ public class SchemaRegionTest {
         -1);
 
     File snapshotDir = new File(config.getSchemaDir() + File.separator + 
"snapshot");
+    snapshotDir.mkdir();
     schemaRegion.createSnapshot(snapshotDir);
 
     schemaRegion.loadSnapshot(snapshotDir);
@@ -97,4 +128,41 @@ public class SchemaRegionTest {
     Assert.assertEquals(1, resultTagMap.size());
     Assert.assertEquals("tag-value", resultTagMap.get("tag-key"));
   }
+
+  @Test
+  @Ignore
+  public void testSnapshotPerformance() throws Exception {
+
+    PartialPath storageGroup = new PartialPath("root.sg");
+    SchemaRegionId schemaRegionId = new SchemaRegionId(0);
+    schemaEngine.createSchemaRegion(storageGroup, schemaRegionId);
+    ISchemaRegion schemaRegion = 
SchemaEngine.getInstance().getSchemaRegion(schemaRegionId);
+
+    Map<String, String> tags = new HashMap<>();
+    tags.put("tag-key", "tag-value");
+
+    long time = System.currentTimeMillis();
+    for (int i = 0; i < 1000; i++) {
+      for (int j = 0; j < 1000; j++) {
+        schemaRegion.createTimeseries(
+            new CreateTimeSeriesPlan(
+                new PartialPath("root.sg.d" + i + ".s" + j),
+                TSDataType.INT32,
+                TSEncoding.PLAIN,
+                CompressionType.UNCOMPRESSED,
+                null,
+                tags,
+                null,
+                null),
+            -1);
+      }
+    }
+    System.out.println("Timeseries creation costs " + 
(System.currentTimeMillis() - time) + "ms.");
+
+    File snapshotDir = new File(config.getSchemaDir() + File.separator + 
"snapshot");
+    snapshotDir.mkdir();
+    schemaRegion.createSnapshot(snapshotDir);
+
+    schemaRegion.loadSnapshot(snapshotDir);
+  }
 }
diff --git 
a/server/src/test/java/org/apache/iotdb/db/metadata/upgrade/MetadataUpgradeTest.java
 
b/server/src/test/java/org/apache/iotdb/db/metadata/upgrade/MetadataUpgradeTest.java
index 2faad460fb..921e51b446 100644
--- 
a/server/src/test/java/org/apache/iotdb/db/metadata/upgrade/MetadataUpgradeTest.java
+++ 
b/server/src/test/java/org/apache/iotdb/db/metadata/upgrade/MetadataUpgradeTest.java
@@ -132,7 +132,11 @@ public class MetadataUpgradeTest {
     Assert.assertTrue(
         new File(schemaDirPath + File.separator + MetadataConstant.TAG_LOG + 
".bak").exists());
     Assert.assertTrue(
-        new File(schemaDirPath + File.separator + 
MetadataConstant.MTREE_SNAPSHOT + ".bak")
+        new File(
+                schemaDirPath
+                    + File.separator
+                    + MetadataConstant.MTREE_SNAPSHOT_OLD_VERSION
+                    + ".bak")
             .exists());
   }
 
@@ -306,7 +310,8 @@ public class MetadataUpgradeTest {
     entityMNode.addChild(measurementMNode);
     entityMNode.addAlias("first", measurementMNode);
     try (MLogWriter mLogWriter =
-        new MLogWriter(schemaDirPath + File.separator + 
MetadataConstant.MTREE_SNAPSHOT)) {
+        new MLogWriter(
+            schemaDirPath + File.separator + 
MetadataConstant.MTREE_SNAPSHOT_OLD_VERSION)) {
       root.serializeTo(mLogWriter);
     }
   }
diff --git a/server/src/test/resources/logback-test.xml 
b/server/src/test/resources/logback-test.xml
index 639c7552df..00b88bfe95 100644
--- a/server/src/test/resources/logback-test.xml
+++ b/server/src/test/resources/logback-test.xml
@@ -42,6 +42,7 @@
     -->
     <logger name="org.apache.iotdb.db.sync" level="INFO"/>
     <logger name="org.apache.iotdb.db.engine.merge" level="INFO"/>
+    <logger name="org.apache.iotdb.db.metadata" level="INFO"/>
     <logger name="org.apache.iotdb.commons.service.ThriftServiceThread" 
level="INFO"/>
     <logger name="org.eclipse.jetty.util.thread.QueuedThreadPool" 
level="INFO"/>
     <logger name="org.apache.iotdb.db.service.metrics.MetricsService" 
level="INFO"/>

Reply via email to