全部产品
Search
文档中心

云数据库 MongoDB:升级MongoDB实例后,各分片Chunks数量不均衡

更新时间:Jul 02, 2026

将云数据库 MongoDB 版分片集群实例升级到6.0版本(小版本7.0.1及以上)或更高版本后,通过sh.status()查看分片信息时,会发现各Shard上的Chunk数量明显不均衡,甚至每个Shard只有1个Chunk。本文说明这一现象的原因,并介绍如何正确判断数据均衡情况。

问题现象

使用云数据库 MongoDB 版分片集群实例时,部分用户在将实例升级到6.0版本(小版本7.0.1及以上)后,通过sh.status()查看分片信息,发现各Shard上的Chunk数量不均衡,与升级前每个Shard上Chunk数量大致相等的情况明显不同。常见的现象包括:

  • 6.0版本(小版本7.0.1起):各Shard上的Chunk数量差异较大,不再像旧版本那样大致相等。

  • 7.0及以上版本:各Shard上可能只有1个Chunk。

通常会产生以下疑问:

  • 数据是不是没有均衡分布?

  • Balancer是不是没有正常工作?

  • 是不是升级出了什么问题?

说明

这是升级后的正常行为,数据仍然是均衡分布的,无需担心。新版本不再以Chunk数量作为均衡标准,而是以实际数据大小为依据。

原因说明

旧版本行为(6.0版本小版本7.0.1之前)

在云数据库 MongoDB 版6.0版本(小版本7.0.1)之前,分片集群的数据均衡机制如下:

  1. 每个Chunk默认最大64 MB。

  2. 当数据写入使Chunk超过64 MB时,会自动分裂(AutoSplit)为多个小Chunk。

  3. Balancer定期检测各Shard上的Chunk数量,发现数量差异超过阈值后执行迁移(moveChunk)。

  4. 最终各Shard上会有大量Chunk,且数量大致相等。

这种机制下,您通过sh.status()能看到每个Shard上有多个Chunk,可以直观地感受到数据是均衡分布的。

6.0版本变化(小版本7.0.1起,对应社区版6.0.3)

云数据库 MongoDB 版从6.0版本(小版本7.0.1)开始,对应社区版MongoDB 6.0.3的Balancer改进,进行了以下重大变更:

  • 取消自动分裂(AutoSplit):Chunk写满后不再自动分裂,仅在迁移前进行必要的分割。

  • 均衡判断标准改变:从基于Chunk数量改为基于实际数据大小。

  • 迁移阈值调整:当不同分片上同一集合的数据大小差异超过3倍ChunkSize(云数据库 MongoDB 版6.0版本起默认ChunkSize为128 MB,即差异超过384 MB)时触发迁移。

  • 术语变更:Chunk概念弱化,改称为Range;moveChunk被moveRange取代。

  • 集合分片前不再需要执行sh.enableSharding()命令。

影响:由于取消了AutoSplit且不再以Chunk数量为均衡依据,各Shard上的Chunk数量可能不相等,这是正常现象。更多信息,请参见sh.enableAutoSplit()。

7.0版本新增:AutoMerger自动合并

从MongoDB 7.0开始,引入了AutoMerger功能:

  • Balancer会自动将同一Shard上可合并的连续Chunk合并在一起。

  • AutoMerger作为均衡操作的一部分在后台运行,默认启用。

  • 每隔autoMergerIntervalSecs秒进行一次自动合并。

  • 如果设置了均衡窗口,AutoMerger仅在该窗口期间运行。

影响:在7.0及以上版本中,由于AutoMerger的存在,各Shard上的Chunk最终可能合并为1个Chunk。这同样是正常行为。更多信息,请参见AutoMerger。

为什么做这些改变?

旧版本基于Chunk数量做均衡判断存在以下问题:

问题

说明

Jumbo Chunk

分片键区分度不足时,同一Chunk中所有文档的分片键相同,Chunk无法分割,导致各Shard的Chunk数量相同但磁盘空间使用不同。

写入倾斜

范围分片键含递增属性时,新数据集中写入一个Shard。

资源消耗

频繁的AutoSplit和moveChunk消耗大量CPU资源,影响业务性能。

新版本基于实际数据大小做均衡判断,更加准确地反映数据分布情况,同时减少了不必要的Chunk分裂和迁移操作。

版本对应关系

云数据库MongoDB版本

对应社区版

Balancer行为

4.4版本

MongoDB 4.4

旧行为:AutoSplit + Chunk数量均衡

5.0版本

MongoDB 5.0

旧行为:AutoSplit + Chunk数量均衡

6.0版本(小版本7.0.0)

MongoDB 6.0.0

旧行为:AutoSplit + Chunk数量均衡

6.0版本(小版本7.0.1起)

MongoDB 6.0.3

取消AutoSplit + 数据大小均衡(Chunk数量可能不均衡)

7.0及以上版本

MongoDB 7.0+

取消AutoSplit + 数据大小均衡 + AutoMerger自动合并Chunk

版本前后对比

对比项

6.0版本(小版本7.0.1之前)

6.0版本(小版本7.0.1起)

7.0及以上版本

自动分裂(AutoSplit)

开启,Chunk写满自动分裂

关闭

关闭

自动合并(AutoMerger)

无

无

开启,自动合并Chunk

均衡判断依据

Chunk数量

实际数据大小

实际数据大小

各Shard的Chunk数量

多个,数量大致相等

不均衡,数量可能不相等

可能合并为1个

迁移阈值

Chunk数量差异≥1(4.2+)

数据大小差异超过3倍ChunkSize

数据大小差异超过3倍ChunkSize

enableSharding命令

分片前必须执行

6.0+可跳过

可跳过

查看均衡方式

sh.status()看Chunk数量

getShardDistribution()看数据大小

getShardDistribution()看数据大小

实测数据

以下为使用YCSB工具分别向4.4、6.0、8.0版本的云数据库 MongoDB 版分片集群实例各插入5000万条数据后的实测结果。

4.4版本(旧行为)

执行sh.status(),重点关注输出中的chunkMetadata字段——每个Shard上有435个Chunk,数量相等,这是旧版本AutoSplit自动分裂的结果:

mongos> sh.status()
shardingVersion
{ _id: 1, clusterId: ObjectId('69fbfda6dec76b373f5eda81') }
---
shards
[
  {
    _id: 'd-uf6d*****04f784',
    host: 'mgset-100239890/10.**.**.1*9:3005,20.**.**.1*9:3002',
    state: 1
  },
  {
    _id: 'd-uf6f*****39f74',
    host: 'mgset-100***91/20.**.**.**7:3002,20.**.**.**8:3002',
    state: 1
  }
]
---
active mongoses
[ { '4.4.30': 2 } ]
---
autosplit
{ 'Currently enabled': 'yes' }
---
balancer
{
  'Currently enabled': 'yes',
  'Failed balancer rounds in last 5 attempts': 0,
  'Currently running': 'no',
  'Migration Results for the last 24 hours': { '947': 'Success' }
}
---
databases
[
  {
    database: {
      _id: 'ycsb',
      primary: 'd-uf6f*****39f74',
      partitioned: true
    },
    collections: {
      'ycsb.test1': {
        shardKey: { _id: 'hashed' },
        unique: false,
        balancing: true,
        chunkMetadata: [
          { shard: 'd-uf6d*****04f784', nChunks: 435 },
          { shard: 'd-uf6f*****39f74', nChunks: 435 }
        ],
        chunks: [
          'too many chunks to print, use verbose if you want to force print'
        ],
        tags: []
      }
    }
  }
]

执行db.test1.getShardDistribution(),关注每个Shard的data(数据大小)和chunks(Chunk数量)字段:

mongos> use ycsb
switched to db ycsb
mongos> db.test1.getShardDistribution()
Shard d-uf6d*****04f784 at mgset-100239890/10.**.**.1*9:3005,20.**.**.1*9:3002
{
  data: '27.2GiB',
  docs: 25014674,
  chunks: 435,
  'estimated data per chunk': '64.04MiB',
  'estimated docs per chunk': 57504
}
---
Shard d-uf6f*****39f74 at mgset-100239891/20.**.**.**7:3002,20.**.**.**8:3002
{
  data: '36.23GiB',
  docs: 33313293,
  chunks: 435,
  'estimated data per chunk': '85.29MiB',
  'estimated docs per chunk': 76582
}
---
Totals
{
  data: '63.44GiB',
  docs: 58327967,
  chunks: 870,
  'Shard d-uf6d*****04f784': [
    '42.88 % data',
    '42.88 % docs in cluster',
    '1KiB avg obj size on shard'
  ],
  'Shard d-uf6f*****39f74': [
    '57.11 % data',
    '57.11 % docs in cluster',
    '1KiB avg obj size on shard'
  ]
}

6.0版本(小版本7.0.1起)

执行sh.status(),关注chunkMetadata字段——各Shard上的Chunk数量明显不均衡(216 vs 1):

mongos> sh.status()
shardingVersion
{ _id: 1, clusterId: ObjectId('69fbfdc420578638757c1d06') }
---
shards
[
  {
    _id: 'd-uf610*****d8904',
    host: 'mgset-100239905/20.**.**.**1:3002,20.**.**.**3:3002',
    state: 1,
    topologyTime: Timestamp({ t: 1778122310, i: 2 })
  },
  {
    _id: 'd-uf6aa*****67314',
    host: 'mgset-100239903/20.**.**.**5:20.**.**.**6:3002',
    state: 1,
    topologyTime: Timestamp({ t: 1778122310, i: 9 })
  }
]
---
active mongoses
[ { '6.0.27': 2 } ]
---
autosplit
{ 'Currently enabled': 'yes' }
---
balancer
{
  'Currently running': 'no',
  'Currently enabled': 'yes',
  'Failed balancer rounds in last 5 attempts': 0,
  'Migration Results for the last 24 hours': { '216': 'Success' }
}
---
databases
[
  {
    database: {
      _id: 'ycsb',
      primary: 'd-uf6aa*****67314',
      partitioned: false,
      version: {
        uuid: UUID('4ee45231-9585-4dba-8f34-f624860e1a79'),
        timestamp: Timestamp({ t: 1778122930, i: 1 }),
        lastMod: 1
      }
    },
    collections: {
      'ycsb.test2': {
        shardKey: { _id: 'hashed' },
        unique: false,
        balancing: true,
        allowMigrations: true,
        chunkMetadata: [
          { shard: 'd-uf610*****d8904', nChunks: 216 },
          { shard: 'd-uf6aa*****67314', nChunks: 1 }
        ],
        chunks: [
          'too many chunks to print, use verbose if you want to force print'
        ],
        tags: []
      }
    }
  }
]

执行db.test2.getShardDistribution(),关注每个Shard的data占比——虽然Chunk数量差异巨大(216 vs 1),但数据仍然均衡分布(50.31% vs 49.68%):

mongos> use ycsb
switched to db ycsb
mongos> db.test2.getShardDistribution()
Shard d-uf6aa*****67314 at mgset-100239903/20.**.**.**5:20.**.**.**6:3002
{
  data: '27.36GiB',
  docs: 32285618,
  chunks: 1,
  'estimated data per chunk': '27.36GiB',
  'estimated docs per chunk': 32285618
}
---
Shard d-uf610*****d8904 at mgset-100239905/20.**.**.**1:3002,20.**.**.**3:3002
{
  data: '27.01GiB',
  docs: 24841944,
  chunks: 216,
  'estimated data per chunk': '128.09MiB',
  'estimated docs per chunk': 115009
}
---
Totals
{
  data: '54.38GiB',
  docs: 57127562,
  chunks: 217,
  'Shard d-uf6aa*****67314': [
    '50.31 % data',
    '56.51 % docs in cluster',
    '1KiB avg obj size on shard'
  ],
  'Shard d-uf610*****d8904': [
    '49.68 % data',
    '43.48 % docs in cluster',
    '1KiB avg obj size on shard'
  ]
}

8.0版本(含AutoMerger)

迁移刚完成时,执行sh.status(),关注chunkMetadata字段——各Shard上仍有多个Chunk(55 vs 1):

mongos> sh.status()
shardingVersion
{ _id: 1, clusterId: ObjectId('69fbfdbdd7b0e3d9551dd833') }
---
shards
[
  {
    _id: 'd-uf65a*****ac94',
    host: 'mgset-100239911/20.**.**.**7:3000,20.**.**.**6:3002',
    state: 1,
    topologyTime: Timestamp({ t: 1778122320, i: 8 }),
    replSetConfigVersion: Long('-1')
  },
  {
    _id: 'd-uf6a8*****c9b14',
    host: 'mgset-100239912/20.**.**.**8:3003,20.**.**.**9:3003',
    state: 1,
    topologyTime: Timestamp({ t: 1778122319, i: 10 }),
    replSetConfigVersion: Long('-1')
  }
]
---
active mongoses
[ { '8.0.18': 2 } ]
---
autosplit
{ 'Currently enabled': 'yes' }
---
balancer
{
  'Currently enabled': 'yes',
  'Failed balancer rounds in last 5 attempts': 0,
  'Currently running': 'no',
  'Migration Results for the last 24 hours': { '216': 'Success' }
}
---
databases
[
  {
    database: {
      _id: 'ycsb',
      primary: 'd-uf6a8*****c9b14',
      version: {
        uuid: UUID('98799357-048e-45bc-a472-387165e0fe74'),
        timestamp: Timestamp({ t: 1778122931, i: 2 }),
        lastMod: 1
      }
    },
    collections: {
      'ycsb.test2': {
        shardKey: { _id: 'hashed' },
        unique: false,
        balancing: true,
        allowMigrations: true,
        chunkMetadata: [
          { shard: 'd-uf65a*****ac94', nChunks: 55 },
          { shard: 'd-uf6a8*****c9b14', nChunks: 1 }
        ],
        chunks: [
          'too many chunks to print, use verbose if you want to force print'
        ],
        tags: []
      }
    }
  }
]

等待AutoMerger自动合并完成后,再次执行sh.status(),关注chunkMetadata字段——每个Shard上的Chunk已自动合并为1个:

mongos> sh.status()
shardingVersion
{ _id: 1, clusterId: ObjectId('69fbfdbdd7b0e3d9551dd833') }
---
shards
[
  {
    _id: 'd-uf65a*****ac94',
    host: 'mgset-100239911/20.**.**.**7:3000,20.**.**.**6:3002',
    state: 1,
    topologyTime: Timestamp({ t: 1778122320, i: 8 }),
    replSetConfigVersion: Long('-1')
  },
  {
    _id: 'd-uf6a8*****c9b14',
    host: 'mgset-100239912/20.**.**.**8:3003,20.**.**.**9:3003',
    state: 1,
    topologyTime: Timestamp({ t: 1778122319, i: 10 }),
    replSetConfigVersion: Long('-1')
  }
]
---
active mongoses
[ { '8.0.18': 2 } ]
---
autosplit
{ 'Currently enabled': 'yes' }
---
balancer
{
  'Currently enabled': 'yes',
  'Failed balancer rounds in last 5 attempts': 0,
  'Currently running': 'no',
  'Migration Results for the last 24 hours': { '216': 'Success' }
}
---
databases
[
  {
    database: {
      _id: 'ycsb',
      primary: 'd-uf6a8*****c9b14',
      version: {
        uuid: UUID('98799357-048e-45bc-a472-387165e0fe74'),
        timestamp: Timestamp({ t: 1778122931, i: 2 }),
        lastMod: 1
      }
    },
    collections: {
      'ycsb.test2': {
        shardKey: { _id: 'hashed' },
        unique: false,
        balancing: true,
        allowMigrations: true,
        chunkMetadata: [
          { shard: 'd-uf65a*****ac94', nChunks: 1 },
          { shard: 'd-uf6a8*****c9b14', nChunks: 1 }
        ],
        chunks: [
          { min: { _id: MinKey() }, max: { _id: Long('-58615400192952365') }, 'on shard': 'd-uf65a*****ac94', 'last modified': Timestamp({ t: 217, i: 2 }) },
          { min: { _id: Long('-58615400192952365') }, max: { _id: MaxKey() }, 'on shard': 'd-uf6a8*****c9b14', 'last modified': Timestamp({ t: 217, i: 1 }) }
        ],
        tags: []
      }
    }
  }
]

执行db.test2.getShardDistribution(),关注每个Shard的data占比——尽管每个Shard只有1个Chunk,数据仍然均衡分布(49.67% vs 50.32%):

mongos> use ycsb
switched to db ycsb
mongos> db.test2.getShardDistribution()
Shard d-uf65a*****ac94 at mgset-100239911/20.**.**.**7:3000,20.**.**.**6:3002
{
  data: '27.01GiB',
  docs: 24841944,
  chunks: 1,
  'estimated data per chunk': '27.01GiB',
  'estimated docs per chunk': 24841944
}
---
Shard d-uf6a8*****c9b14 at mgset-100239912/20.**.**.**8:3003,20.**.**.**9:3003
{
  data: '27.37GiB',
  docs: 35898246,
  chunks: 1,
  'estimated data per chunk': '27.37GiB',
  'estimated docs per chunk': 35898246
}
---
Totals
{
  data: '54.39GiB',
  docs: 60740190,
  chunks: 2,
  'Shard d-uf65a*****ac94': [
    '49.67 % data',
    '40.89 % docs in cluster',
    '1KiB avg obj size on shard'
  ],
  'Shard d-uf6a8*****c9b14': [
    '50.32 % data',
    '59.1 % docs in cluster',
    '1KiB avg obj size on shard'
  ]
}

结论:三个版本的实测数据表明,无论Chunk数量如何变化(870→217→2),数据始终均衡分布在各Shard上。Chunk数量的差异仅是内部管理机制的变化,不影响实际数据分布和业务。

如何正确判断数据是否均衡

升级到6.0版本(小版本7.0.1)及以上版本后,请使用以下方式判断数据均衡情况:

推荐方式:getShardDistribution()

连接到mongos后执行以下命令:

use <your_database>
db.<your_collection>.getShardDistribution()

该命令会返回每个Shard上该集合的数据大小、文档数量和占比,能真实反映数据分布情况。

辅助方式:db.stats()

use <your_database>
db.stats()

可以查看数据库在各Shard节点的整体数据存储情况。

不再推荐:sh.status()看Chunk数量

sh.status()仍然可以执行,但Chunk数量不再反映数据均衡情况。看到各Shard的Chunk数量不相等或只有1个Chunk都是正常的,不代表数据分布有问题。

常见问题

Q:升级后Chunk数量不均衡或变为1,数据会丢失吗?

A:不会。Chunk只是MongoDB内部管理数据的逻辑单元,Chunk数量的变化不影响实际数据。数据仍然完整保存在各Shard上。

Q:需要手动执行split命令来分割Chunk吗?

A:不需要。新版本的Balancer会在需要迁移数据时自动进行必要的分割,无需手动干预。

Q:升级后Balancer还在工作吗?

A:是的。Balancer仍在正常工作,只是判断标准从Chunk数量改为了数据大小。当各分片间的数据大小差异超过阈值时,Balancer会自动执行数据迁移。

Q:6.0和7.0版本升级后的Chunk表现有什么不同?

A:6.0版本(小版本7.0.1起)取消了AutoSplit并改用数据大小均衡,各Shard的Chunk数量可能不均衡。7.0版本在此基础上新增了AutoMerger,会自动合并Chunk,最终每个Shard可能只有1个Chunk。两种情况下数据都是均衡分布的。

Q:迁移过程中看到多个Chunk是正常的吗?

A:是正常的。在数据迁移期间,Balancer会对数据进行必要的分割,因此会临时出现多个Chunk。对于7.0及以上版本,迁移完成后AutoMerger会自动合并这些Chunk;对于6.0版本,这些Chunk可能会保持不变,但不影响数据均衡。

Q:这个变化影响我的业务吗?

A:不影响。这个改变对业务是透明的,实际上新版本减少了不必要的Chunk分裂和迁移操作,性能反而更好。

参考文档