Help Center/ Document Database Service/ User Guide/ Database Usage/ Managing Time Roaming Snapshots Using Commands
Updated on 2025-03-20 GMT+08:00

Managing Time Roaming Snapshots Using Commands

On September 30, 2024, DDS 4.2 and 4.4 started to support time roaming. You can run the snapshot command to create a time roaming snapshot at a specified time point. This command takes a snapshot of all user database data at the current time point. After the snapshot is created, you can specify a readAt parameter to read the data of the time roaming snapshot using the find or getmore operation in DDS. This feature is used for the following purposes:

  • Reports are generated for historical data, eliminating the need for you to shard databases and tables by time.
  • Data is backed up for point-in-time recovery without affecting service reads and writes.

This feature allows you to manage multiple pieces of historical data in a DB instance or even in the same tablespace.

Precautions

  • Currently, only DDS 4.2 and 4.4 support this feature. If your instance version is too early, upgrade it by referring to Upgrading a Minor Engine Version.
  • Time roaming snapshots are persistent and are retained after a DB instance is restarted.
  • You can create a maximum of eight time roaming snapshots for a DB instance. The snapshot name can contain digits (0-9), letters (a-z or A-Z), and underscores (_), for example, Snapshot_2024_09_30_15_18.
  • Time roaming snapshots contain data of all user databases at the current time. The database account used to deliver commands must have at least the {role: "dbAdminAnyDatabase"} permission. For details about how to create a database account, see Creating a User.
  • The time roaming snapshot command can be delivered only to the primary node (or mongos node in a cluster instance) and synchronized to the standby node in oplog. To avoid possible rollback caused by a primary/standby switchover, set writeConcern to majority to create and delete time roaming snapshots.
  • Do not change the metadata of related collections (including deleting or renaming collections, and creating or deleting indexes) during the validity period of a time roaming snapshot. Operations on metadata will invalidate the snapshots of the corresponding collections, but will not affect the snapshots of other collections.
  • Do not delete snapshots when reading a time roaming snapshot.
  • Creating a time roaming snapshot does not occupy extra disk space. However, this operation prevents snapshot-related data from being compacted by the storage engine. If a new write operation is performed after a time roaming snapshot is created, check the disk usage of the DB instance in a timely manner. For details about the storage engine, see Q&A About Switching Storage Engine to RocksDB for DDS 4.2 and Later Versions.
  • Data related to time roaming snapshots is not compacted by the storage engine. If a large number of time roaming snapshots are created, the write performance of the DB instance decreases by 5% to 10%.
  • To enable time roaming snapshots on a cluster instance, you need to disable the balancer. For details about how to manage the balancer, see How Do I Manage the Balancer?

Prerequisites

A DDS instance has been connected. For details, see Connecting to a DB Instance.

Creating a Time Roaming Snapshot

  1. Go to the CLI of the primary node of a DDS replica set instance or a mongos node of a DDS cluster instance, and switch to the user database.
    use test // It can be any user database, which does not affect the final result.
  2. Run the following command to create a time roaming snapshot:
    db.runCommand({snapshot: 1, op: "create", name: "s1"})    // creates a time roaming snapshot named s1.
    db.runCommand({snapshot: 1, op: "create"}) // If the name parameter is not specified, stable is used as the snapshot name by default.

Viewing Time Roaming Snapshots

  1. Go to the CLI of the primary node of a DDS replica set instance or a mongos node of a DDS cluster instance, and switch to the user database.
    use test // It can be any user database, which does not affect the final result.
  2. Run the following command to view time roaming snapshots at the current time:
db.runCommand({snapshot: 1, op: "list"}) // {snapshot: 1, op: "list"} 
// {snapshot: 1, op: "list"} execution result
{
	"snapshotList" : [
		"s1",
		"stable"
	],
	"ok" : 1,
	"operationTime" : Timestamp(1727683917, 1),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1727683917, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}

Deleting a Time Roaming Snapshot

  1. Go to the CLI of the primary node of a DDS replica set instance or a mongos node of a DDS cluster instance, and switch to the user database.
    use test // It can be any user database, which does not affect the final result.
  2. Run the following command to delete a time roaming snapshot:
    db.runCommand({snapshot:1, op:"delete", name:"s1"})    // deletes a time roaming snapshot named s1.
    db.runCommand({snapshot:1, op:"delete"})    // If the name parameter is not specified, the time roaming snapshot named stable is deleted by default. db.runCommand({snapshot:1, op:"delete", name:"*"})    // If the name parameter is set to *, all time roaming snapshots are deleted.

Reading a Time Roaming Snapshot Using find/getMore

  1. Go to the CLI of the primary node of a DDS replica set instance or a mongos node of a DDS cluster instance.
  2. Run the find command to read a time roaming snapshot. The readAt parameter needs to be specified. The find command needs to be delivered in runCommand mode. For details, see find.
    PRIMARY> use test 
    PRIMARY> db.foo.insert({a:1, c:1})
    PRIMARY> db.foo.insert({a:2, c:2}) 
    //Create a time roaming snapshot named s1.
    PRIMARY> db.runCommand({snapshot:1, op:"create", name:"s1"}) 
    //Change the file {a:1, c:1} to {a:1, c:3} after the snapshot is created.
    PRIMARY> db.foo.update({a:1}, {$set:{c:3}}) 
    //Run the find command on the time roaming snapshot named s1 to query the files that meet the condition {a:1}.
    PRIMARY> db.runCommand({find:"foo", filter:{a:1}, readAt:"s1"})
    {
            "cursor" : {
                    "firstBatch" : [
                            {
                                    "_id" : ObjectId("5dd75662b9c50d4bdca52721"),
                                    "a" : 1,
                                    "c" : 1
                            },
                    ],
                    "id" : NumberLong(0),
                    "ns" : "test.foo"
            },
            "ok" : 1
    }

    In the find command, if readAt: s1 is specified, data is read from snapshot s1. If filter: {a:1} is specified, all files that meet the condition a=1 are filtered. As shown in the preceding example, after snapshot s1 is created, the operation of updating {a:1, c:1} to {a:1, c:3} does not affect the snapshot data.

  3. Run the getMore command to read a time roaming snapshot. For details about the getMore command format, see getMore.
    PRIMARY> use test 
    PRIMARY> db.foo.insert({a:1, c:1})
    PRIMARY> db.foo.insert({a:2, c:2}) 
    //Create a time roaming snapshot named s1.
    PRIMARY> db.runCommand({snapshot:1, op:"create", name:"s1"}) 
    //Change the file {a:1, c:1} to {a:1, c:3} after the snapshot is created.
    PRIMARY> db.foo.update({a:1}, {$set:{c:3}}) 
    //On the time roaming snapshot s1, run the find command to query all files that meet the condition a≤2 and set batchSize to 0.
    PRIMARY> db.runCommand({getMore: NumberLong("47677869455"), collection:"foo"})
    {
            "cursor" : {
                    "nextBatch" : [
                            {
                                    "_id" : ObjectId("5dd75662b9c50d4bdca52721"),
                                    "a" : 1,
                                    "c" : 1
                            },
                            {
                                    "_id" : ObjectId("5dd75687b9c50d4bdca52723"),
                                    "a" : 2,
                                    "c" : 2
                            }
                    ],
                    "id" : NumberLong(0),
                    "ns" : "test.foo"
            },
            "ok" : 1
    }

    In the getMore command, if you specify readAt: s1 in the find command, data is read from snapshot s1. If you specify filter: {a: {$lte: 2}}, all files that meet the condition a≤2 are filtered. As shown in the preceding example, after snapshot s1 is created, the operation of updating {a:1, c:1} to {a:1, c:3} does not affect the snapshot data.