Remove Shards from a Sharded Cluster
On this page
To remove a shard you must ensure the shard's data is migrated to the remaining shards in the cluster. This procedure describes how to safely migrate data and remove a shard.
About this Task
Creating, sharding, or moving collections while performing this procedure may cause interruptions and lead to unexpected results.
Do not use this procedure to migrate an entire cluster to new hardware. To migrate, see Migrate a Self-Managed Sharded Cluster to Different Hardware.
When you remove a shard in a cluster with an uneven chunk distribution, the balancer first removes the chunks from the draining shard and then balances the remaining uneven chunk distribution.
Removing a shard may cause an open change stream cursor to close, and the closed change stream cursor may not be fully resumable.
You can safely restart a cluster during a shard removal process. If you restart a cluster during an ongoing draining process, draining continues automatically after the cluster components restart. MongoDB records the shard draining status in the
config.shards
collection.
Before you Begin
This procedure uses the
sh.moveCollection()
method to move collections off of the removed shard. Before you begin this procedure, review themoveCollection
considerations and requirements to understand the command behavior.To remove a shard, first connect to one of the cluster's
mongos
instances usingmongosh
.
Steps
Ensure the balancer is enabled
To migrate data from a shard, the balancer process must
be enabled. To check the balancer state, use the
sh.getBalancerState()
method:
sh.getBalancerState()
If the operation returns true
, the balancer is enabled.
If the operation returns false
, see
Enable the Balancer.
Determine the name of the shard to remove
To find the name of the shard, run the listShards
command:
db.adminCommand( { listShards: 1 } )
The shards._id
field contains the shard name.
Remove chunks from the shard
Run the removeShard
command for the shard you want to
remove:
db.adminCommand( { removeShard: "<shardName>" } )
Note
mongos
converts the
write concern of the
removeShard
command to "majority"
.
The removeShard
operation returns:
{ "msg" : "draining started successfully", "state" : "started", "shard" : "<shardName>", "note" : "you need to drop or movePrimary these databases", "dbsToMove" : [ "db1", "db2" ], "ok" : 1, "operationTime" : Timestamp(1575398919, 2), "$clusterTime" : { "clusterTime" : Timestamp(1575398919, 2), "signature" : { "hash" : BinData(0,"Oi68poWCFCA7b9kyhIcg+TzaGiA="), "keyId" : NumberLong("6766255701040824328") } } }
The shard enters the draining
state and the balancer begins
migrating chunks from the removed shard to other shards in the
cluster. These migrations happens slowly to avoid severe impact on
the overall cluster. Depending on your network capacity and the
amount of data, this operation can take from a few minutes to
several days to complete.
Tip
While the shard is in the draining
state, you can use the
reshardCollection command to redistribute
data off of the removed shard.
Moving data with reshardCollection
can be faster than
waiting for the balancer to migrate chunks. The cluster ensures
that data is not placed on any draining shards. You can't run
moveCollection
and reshardCollection
operations
simultaneously.
List sharded collection namespaces
To return a list of sharded collection namespaces, use the
$shardedDataDistribution
stage and project the ns
field:
use admin db.aggregate( [ { $shardedDataDistribution: { } }, { $project: { ns: 1 } } ] )
Record the output to reference later in this tutorial.
Move collections off of the shard
For each database in the cluster, excluding admin and config, perform these steps:
List the database collections
List the collections in the database, omitting the following types of collections:
Internal collections that support CSFLE
System collections
Time series collections
Views
use <databaseName> db.getCollectionInfos( { $and: [ { type: { $nin: [ "view", "timeseries" ] } }, { name: { $not: { $regex: "^system\." } } }, { name: { $not: { $regex: "^enxcol_\..*(\.esc|\.ecc|\.ecoc|\.ecoc\.compact)$" } } } ] }, { nameOnly: true } ) Move necessary collections
For each collection returned by
getCollectionInfos()
perform the following steps.Note
Only one
moveCollection
operation can be in progress at a time. Complete all sub-steps before moving on to the next collection.Determine whether the collection needs to be moved.
Run the
$collStats
aggregation stage and project thens
andshard
fields:db.<collName>.aggregate( [ { $collStats: { } }, { $project: { ns: 1, shard: 1 } } ] ) If any of the following criteria are met, skip the collection and return to step
i
for the next collection in the database:The
ns
field is present in the$shardedDataDistribution
output from step 4.The
shard
field is not the shard being removed.
If neither of the preceding criteria are met, continue to step
ii
for the current collection.Move the collection.
To move the collection, run
sh.moveCollection()
on the collection:sh.moveCollection( "<namespace>.<collection>", "<ID of recipient shard>" ) Note
moveCollection
fails if you run the command on a namespace that is sharded. If you receive this error message, ignore it and return to stepi
for the next collection.Return to step
i
for each collection in the database.
Repeat the procedure for other databases
Repeat step 6, Move collections off of the shard (and sub-steps) for each database in the cluster.
Change primary shard
Run the db.printShardingStatus()
method:
db.printShardingStatus()
In the databases
section of the command output, check the
database.primary
field. If the primary
field is the
removed shard, you must move that database's primary to a
different shard.
To change a database's primary shard, run the movePrimary
command.
Warning
When you run movePrimary
, any collections that were not
moved in the Move collections off of the shard step
are unavailable during the movePrimary
process.
db.adminCommand( { movePrimary: <dbName>, to: <shardName> } )
Check migration status
To check the progress of the migration, run
removeShard
from the admin
database again:
db.adminCommand( { removeShard: "<shardName>" } )
In the output, the remaining
field includes these fields:
Field | Description |
---|---|
chunks | Number of chunks currently remaining on the shard |
dbs | Number of databases whose primary shard is the shard. These databases are specified in
the dbsToMove output field. |
jumboChunks | Of the total number of If After the |
Continue checking the status of the removeShard
command until the
number of chunks remaining is 0.
db.adminCommand( { removeShard: "<shardName>" } )
Finalize shard removal
To finalize the shard removal process, re-run the removeShard
command:
db.adminCommand( { removeShard: <shardName> } )
Note
DDL Operations
If you remove a shard while your cluster executes a DDL
operation (an operation that modifies a collection such as
reshardCollection
), the removeShard
operation
runs after the concurrent DDL operation finishes.
If the shard is removed, the command output resembles the following:
{ msg: 'removeshard completed successfully', state: 'completed', shard: '<shardName>', ok: 1, '$clusterTime': { clusterTime: Timestamp({ t: 1721941519, i: 7 }), signature: { hash: Binary.createFromBase64('AAAAAAAAAAAAAAAAAAAAAAAAAAA=', 0), keyId: Long('0') } }, operationTime: Timestamp({ t: 1721941519, i: 7 }) }