This topic describes how to monitor the progress of tasks that add or remove shard nodes and how to identify abnormal conditions that may block these tasks.
Background information
After you add or remove shard nodes from a sharded cluster instance, the task might remain incomplete for an extended period. The following sections explain how to troubleshoot this issue.
Before you begin, understand the following concepts:
-
Understand the deployment modes of MongoDB replica set instances and sharded cluster instances, and the differences between these architectures. For more information, see Replica set architecture and Sharded cluster architecture.
-
Understand how the MongoDB Balancer works. For more information, see Manage the MongoDB Balancer.
-
Understand how MongoDB divides data. MongoDB partitions data into chunks.
-
Understand common O&M commands for MongoDB sharded cluster instances, such as
sh.status(). -
Understand how to use mongo shell, mongosh, or other visualization tools.
Check task progress
Step 1: Check whether the Balancer is enabled
Chunk migration during shard addition or removal depends on the Balancer. If the Balancer is disabled, the following issues occur:
-
When adding a shard node: Chunk data cannot migrate to the new shard node, and the node cannot handle service traffic.
-
When removing a shard node: Chunks on the target shard cannot migrate away, blocking the removal task.
Enable the Balancer to ensure normal chunk migration. For instructions, see Manage the MongoDB Balancer.
Use one of the following methods to check whether the Balancer is enabled:
-
Method 1: Run the
sh.status()command.If the Balancer is enabled, the output resembles the following example.
... autosplit: Currently enabled: yes balancer: Currently enabled: yes Currently running: yes Balancer active window is set between 08:30 and 11:30 server local time ...If the output shows
“Currently enabled: no”, the Balancer is disabled. -
Method 2: Run the
sh.getBalancerState()command.-
If the command returns
true, the Balancer is enabled. -
If the command returns
false, the Balancer is disabled.
-
Step 2: Check whether the Balancer window is too short
The Balancer controls chunk migration speed and only migrates chunks during its active window. If migration does not finish within the current window, it resumes in the next window until complete. A short window can slow down shard addition or removal tasks. To adjust the Balancer window, see Manage the MongoDB Balancer.
Use one of the following methods to check the Balancer window:
-
Method 1: Run the
sh.status()command.The following example shows a Balancer window from 08:30 to 11:30 local server time (3 hours total).
... autosplit: Currently enabled: yes balancer: Currently enabled: yes Currently running: yes Balancer active window is set between 08:30 and 11:30 server local time ... -
Method 2: Run the
sh.getBalancerWindow()command.The following example clearly displays the window time, especially useful when many sharded collections exist.
{ "start" : "08:30", "stop" : "11:30" }
Step 3: Gather information needed to estimate task progress
For MongoDB versions earlier than 6.0
This section applies to the following versions:
-
MongoDB instances earlier than version 6.0.
-
MongoDB 6.0 instances with a minor engine version earlier than 7.0.1 (baseline version 6.0.3). To check your minor engine version, see MongoDB minor version guide.
Before estimating task progress, obtain Balancer run statistics (success and failure counts) and chunk information for sharded collections awaiting migration.
You can obtain the Balancer's execution results and information about chunks of sharded tables pending migration using the following two methods:
-
Method 1: Use output from the
sh.status()command.Focus on two parts of the
sh.status()output. The first part shows recent Balancer results, as in this example.... balancer: Collections with active migrations: <db>.<collection> started at Wed Sep 27 2023 10:25:21 GMT+0800 (CST) Failed balancer rounds in last 5 attempts: 0 Migration Results for the last 24 hours: 300 : Success databases: ...The second part shows chunk details for sharded collections, as in this example.
... databases: ... { "_id" : "<db>", "primary" : "d-xxxxxxxxxxxxxxx3", "partitioned" : true, "version" : { "uuid" : UUID("3409a337-c370-4425-ad72-8b8c6b0abd52"), "lastMod" : 1 } } <db>.<collection> shard key: { "<shard_key>" : "hashed" } unique: false balancing: true chunks: d-xxxxxxxxxxxxxxx1 13630 d-xxxxxxxxxxxxxxx2 13629 d-xxxxxxxxxxxxxxx3 13652 d-xxxxxxxxxxxxxxx4 13630 d-xxxxxxxxxxxxxxx5 3719 too many chunks to print, use verbose if you want to force print ...In this example, “d-xxxxxxxxxxxxxxx5” is the newly added shard node. You can also run the
getShardDistributioncommand in the database containing the sharded collection to obtain chunk distribution details, as shown below.use <db> db.<collection>.getShardDistribution() -
Method 2: Read relevant data directly from the config database.
View chunk statistics aggregated by shard as follows.
db.getSiblingDB("config").chunks.aggregate([{$group: {_id: "$shard", count: {$sum: 1}}}])To view chunks on a specific shard grouped by namespace, run the following command.
db.getSiblingDB("config").chunks.aggregate([{$match: {shard: "d-xxxxxxxxxxxxxx"}},{$group: {_id: "$ns", count: {$sum: 1}}}])To count chunks successfully migrated to a specific shard node in the past 24 hours, run the following command.
// details.to specifies the destination shard for chunk migration // Use ISODate to define the time range in the time field db.getSiblingDB("config").changelog.find({"what" : "moveChunk.commit", "details.to" : "d-xxxxxxxxxxxxx","time" : {"$gte": ISODate("2023-09-26T00:00:00")}}).count()
For MongoDB versions 6.0 and later
This section applies to the following versions:
-
MongoDB instances version 6.0 and later.
-
MongoDB 6.0 instances with a minor engine version 7.0.1 (baseline version 6.0.3) or later. To check your minor engine version, see MongoDB minor version guide.
Before estimating task progress, focus on data distribution across shards. You can still use sh.status() output as a reference, but shift attention from uneven chunk counts to actual data volume distribution.
-
Obtain sharded collection distribution and data balance information.
Use the
getShardDistributioncommand to obtain distribution details and focus on data balance. Example:mongos> db.xxx.getShardDistribution() Shard d-xxx at xxx data : 379.26MiB docs : 8277367 chunks : 1 estimated data per chunk : 379.26MiB estimated docs per chunk : 8277367 Shard d-xxx at xxx data : 379.11MiB docs : 8272852 chunks : 1 estimated data per chunk : 379.11MiB estimated docs per chunk : 8272852 Shard d-xxx at xxx data : 379.18MiB docs : 8275108 chunks : 1 estimated data per chunk : 379.18MiB estimated docs per chunk : 8275108 Totals data : 1.11GiB docs : 24825327 chunks : 3 Shard d-xxx contains 33.34% data, 33.34% docs in cluster, avg obj size on shard : 48B Shard d-xxx contains 33.32% data, 33.32% docs in cluster, avg obj size on shard : 48B Shard d-xxx contains 33.33% data, 33.33% docs in cluster, avg obj size on shard : 48BYou can also run the following command for more detailed distribution information (including document count, total size, orphaned document count, and orphaned size):
db.getSiblingDB("admin").aggregate( [{ $shardedDataDistribution: { } },{ $match: { "ns": "<db>.<collection>" } }] ).pretty()The following example output shows noticeable data imbalance across shards.
{ "ns" : "<db>.<collection>", "shards" : [ { "shardName" : "d-xxxxxxxxxxxxxxx1", "numOrphanedDocs" : 0, "numOwnedDocuments" : 504298920, "ownedSizeBytes" : NumberLong("833101815840"), "orphanedSizeBytes" : 0 }, { "shardName" : "d-xxxxxxxxxxxxxxx2", "numOrphanedDocs" : 0, "numOwnedDocuments" : 250283901, "ownedSizeBytes" : NumberLong("409714745937"), "orphanedSizeBytes" : 0 }, { "shardName" : "d-xxxxxxxxxxxxxxx3", "numOrphanedDocs" : 0, "numOwnedDocuments" : 109098088, "ownedSizeBytes" : NumberLong("178157177704"), "orphanedSizeBytes" : 0 }, { "shardName" : "d-xxxxxxxxxxxxxxx4", "numOrphanedDocs" : 0, "numOwnedDocuments" : 382018055, "ownedSizeBytes" : NumberLong("630329790750"), "orphanedSizeBytes" : 0 } ] }From this output, you can determine that the instance has 4 shard nodes and the total data volume for the sharded collection
<db>.<collection>is approximately 2051303530231 bytes (833101815840 + 409714745937 + 178157177704 + 630329790750 = 2051303530231), or about 1910.4 GB. -
View successfully migrated data volume over the past day.
Run the following query:
pipeline = [ { '$match': { 'what': 'moveChunk.commit', } }, { '$group': { '_id': { 'date': { '$dateToString': { 'format': '%Y-%m-%d', 'date': '$time'} }, }, 'chunks_moved': { '$sum': 1 }, 'docs_moved': { '$sum': '$details.counts.cloned' }, 'bytes_moved': { '$sum': '$details.counts.clonedBytes' }, } }, { '$sort': { '_id.date': -1} }, ] db.getSiblingDB("config").changelog.aggregate(pipeline)Example output:
mongos> db.getSiblingDB("config").changelog.aggregate(pipeline) { "_id" : { "date" : "2024-09-24" }, "chunks_moved" : 91, "docs_moved" : NumberLong(33071040), "bytes_moved" : NumberLong("11532786734") } { "_id" : { "date" : "2024-09-23" }, "chunks_moved" : 294, "docs_moved" : NumberLong(109806635), "bytes_moved" : NumberLong("38294757573") } { "_id" : { "date" : "2024-09-22" }, "chunks_moved" : 737, "docs_moved" : NumberLong(266800041), "bytes_moved" : NumberLong("93047288531") } { "_id" : { "date" : "2024-09-21" }, "chunks_moved" : 1448, "docs_moved" : NumberLong(525308393), "bytes_moved" : NumberLong("183117965820") } { "_id" : { "date" : "2024-09-20" }, "chunks_moved" : 1459, "docs_moved" : NumberLong(530020503), "bytes_moved" : NumberLong("184390749022") } { "_id" : { "date" : "2024-09-19" }, "chunks_moved" : 1478, "docs_moved" : NumberLong(557833705), "bytes_moved" : NumberLong("186910196651") } { "_id" : { "date" : "2024-09-18" }, "chunks_moved" : 1360, "docs_moved" : NumberLong(508484825), "bytes_moved" : NumberLong("173486932689") }This output shows that on
2024-09-21, 183117965820 bytes (about 170.5 GB) were migrated.
Step 4: Estimate task progress and completion time
For MongoDB versions earlier than 6.0
This section applies to the following versions:
-
MongoDB instances earlier than version 6.0.
-
MongoDB 6.0 instances with a minor engine version earlier than 7.0.1 (baseline version 6.0.3). To check your minor engine version, see MongoDB minor version guide.
After obtaining the number of successfully migrated chunks and current data distribution, estimate overall task progress and expected completion time.
Assume the following ideal conditions during shard addition: total chunk count remains constant, shard count stays fixed (no concurrent shard additions or removals), service load remains stable, and Balancer parameters use default values. Using the example from Step 3 under For MongoDB versions earlier than 6.0, you know:
-
There are 5 shard nodes.
-
300 chunks migrated successfully during the Balancer window.
-
The sharded collection
<db>.<collection>has 58260 total chunks (13630 + 13629 + 13652 + 13630 + 3719 = 58260).
Therefore, the following can be calculated:
-
At equilibrium, each shard should hold 11652 chunks (58260 ÷ 5 = 11652).
-
At the current migration rate, task completion requires another 26.4 days ((11652 – 3719) ÷ 300 ≈ 26.4).
-
The shard addition task is 32% complete (3719 ÷ 11652 = 32%).
In real-world scenarios, total chunk count increases due to ongoing writes and chunk splits. This calculation assumes ideal conditions; actual completion time may be longer.
For MongoDB versions 6.0 and later
This section applies to the following versions:
-
MongoDB instances version 6.0 and later.
-
MongoDB 6.0 instances with a minor engine version 7.0.1 (baseline version 6.0.3) or later. To check your minor engine version, see MongoDB minor version guide.
Assume the sharded cluster instance has only one collection requiring balancing. Using the example from Step 3 under For MongoDB versions 6.0 and later, you know:
-
There are 4 shard nodes.
-
On
2024-09-21, approximately 170.5 GB (183117965820 bytes) were migrated. -
The sharded collection
<db>.<collection>has a total data volume of about 1910.4 GB (2051303530231 bytes).
Therefore, the following can be calculated:
-
At equilibrium, each shard should hold roughly 477.6 GB (512825882557.75 bytes).
-
The total data volume needing migration to reach equilibrium is 875559682949 bytes (815.4 GB), broken down as follows:
Shard1 needs to migrate 320275933282.25 bytes (833101815840 – 512825882557.75).
Shard2 needs to migrate 103111136620.75 bytes (409714745937 – 512825882557.75).
Shard3 needs to migrate 334668704853.75 bytes (178157177704 – 512825882557.75).
Shard4 needs to migrate 117503908192.25 bytes (630329790750 – 512825882557.75).
(320275933282.25 + 103111136620.75 + 334668704853.75 + 117503908192.25 = 875559682949)
-
At the current migration rate, equilibrium will be reached in about 4.8 days (815.4 GB ÷ 170.5 GB/day ≈ 4.8 days).
Step 5: Check whether the task flow is blocked (shard removal)
If the shard removal task is blocked, the sh.status() output shows no successful chunk migrations in recent periods, and the shard being removed still has chunks that have not migrated. In this case, the shard removal task cannot complete, and other O&M operations on the instance in the ApsaraDB for MongoDB console are also affected.
The following example shows the sh.status() output in this scenario.
autosplit:
Currently enabled: yes
balancer:
Currently enabled: yes
Currently running: no
Balancer lock taken at Wed Sep 30 2020 02:03:11 GMT+0800 (CST) by ConfigServer:Balancer
Failed balancer rounds in last 5 attempts: 0
Migration Results for the last 24 hours:
No recent migrations
databases:
{ "_id" : "report", "primary" : "d-0xixxx", "partitioned" : true }
report.report
shard key: { "GsId" : "hashed" }
unique: false
balancing: true
chunks:
d-0xixxx 9
d-0xixxx 2133
d-0xixxx 2152
d-0xixxx 2116
d-0xixxx 2133
too many chunks to print, use verbose if you want to force print
This issue is likely caused by jumbo chunks blocking the shard removal process. Run the following command to check for jumbo chunks.
db.getSiblingDB("config").chunks.aggregate([{$match: {shard: "d-xxxxxxxxxxxxxx", jumbo:true}},{$group: {_id: "$ns", count: {$sum: 1}}}])
Jumbo chunks are typically caused by an inappropriate shard key design, such as hot keys. Before proceeding, classify the jumbo chunks into one of the following categories:
-
Splittable: The chunk size exceeds
chunkSize, but the chunk can still be split into smaller chunks based on the shard key. No special handling is required. The Balancer migrates the chunk after it is split. -
Unsplittable: Most data in the chunk shares the same shard key value (hot key). The data size exceeds
chunkSizeand the chunk cannot be split. Use one of the following methods to handle this type.
Try the following methods based on your business requirements:
-
Method 1: Optimize the shard key design (root fix for hot key issues)
-
For MongoDB 4.4 or later, use the refineCollectionShardKey command to add suffix fields to the existing shard key. This increases the cardinality of the shard key and makes previously unsplittable jumbo chunks splittable.
-
For MongoDB 5.0 or later, you can also use the reshardCollection command to reshard the collection with a new shard key. For more information, see Reshard a Collection.
-
-
Method 2: Migrate the jumbo chunk (for MongoDB 4.4 or later, such as when a jumbo chunk cannot be migrated away during shard removal)
-
Option 1 (recommended): Run the clearJumboFlag command to clear the jumbo flag of the chunk, and then set the Balancer parameter
attemptToBalanceJumboChunkstotrueto let the Balancer automatically migrate the chunk. This method does not block writes during data copying. Writes are blocked only briefly during the final stage of migration.Important-
If the write volume on the chunk is high, the migration may fail due to incremental cache overflow. After the failure, the chunk is re-marked as jumbo. Clear the flag again and retry.
-
After the migration succeeds, immediately set
attemptToBalanceJumboChunksback tofalse. For MongoDB 6.0 or later, the Balancer balances based on data volume differences between shards. After the oversized chunk is migrated to any shard, that shard becomes the data volume outlier. If you do not restore the setting, the Balancer migrates the chunk back and forth between shards, causing continuous data transfer and orphan document cleanup overhead. After you restore the setting, the chunk is re-marked as jumbo when the next regular migration attempt fails and is no longer moved. This is expected and does not require clearing the flag again.
-
-
Option 2: Run the
moveChunkcommand with theforceJumbo: trueoption. This method blocks all writes to the collection on the source shard during data copying, which may last for hours for large chunks. Use this method only during off-peak hours or when writes can be paused. We recommend that you perform this operation with assistance from Alibaba Cloud technical support.
-
-
Method 3: Delete data. If some business data can be deleted, remove data from the jumbo chunk to reduce its size. Note: After the chunk becomes smaller, the jumbo flag is not automatically cleared. You must still run the
clearJumboFlagcommand (or wait until the chunk is successfully split) before the Balancer can migrate it. -
Method 4: Increase the chunkSize parameter. Increase the
chunkSizeparameter to change the jumbo chunk threshold. This method is effective only when the actual chunk size slightly exceeds the current threshold. It does not help with oversized chunks caused by hot keys. We recommend that you perform this operation with assistance from Alibaba Cloud technical support.
If none of the preceding methods resolve the issue, submit a ticket to contact technical support.
Accelerate adding or deleting task processes
To complete shard addition or removal faster, try these acceleration methods:
-
Increase the Balancer window duration. Note that chunk migration adds extra load that may affect your service. Assess risks before adjusting. For instructions, see Manage the MongoDB Balancer.
-
Adjust the setParameter.chunkMigrationConcurrency parameter to change chunk migration concurrency. For details, see Parameter tuning recommendations.
-
Manually run
moveChunkoperations during off-peak hours. For more information, see sh.moveChunk(). Example:sh.moveChunk("<db>.<collection>", {"<shard_key>": <value>}, "d-xxxxxxxxxxxxx") // example: sh.moveChunk("records.people", { zipcode: "53187" }, "shard0019") -
submit a ticket to request technical support for kernel parameter adjustments.