深入解析 MongoDB 中的 renameCollection 操作:不同版本中的风险与影响

数据库 MongoDB
在进行 renameCollection 操作时,请务必谨慎操作。这个操作可能会对线上系统产生重大影响,因此建议在非高峰时段进行,并且提前备份数据以防万一。

在 MongoDB 中,renameCollection 操作用于将一个集合重命名为另一个名称。虽然这看起来是一个简单的操作,但在不同版本的 MongoDB 中,renameCollection 有一些重大的变化和注意事项。本文将深入探讨在不同版本的 MongoDB 中执行 renameCollection 操作时需要考虑的方面。

MongoDB 3.4 版本

renameCollection is suitable for production environments; however:

  • renameCollection blocks all database activity for the duration of the operation.
  • renameCollection is not compatible with sharded collections.
  • renameCollection fails if is the name of an existing collection and you do not specify .targetdropTarget: true
  • You cannot rename a collection from a replicated database to the database, which is not replicated.local
  • You cannot rename a collection from the database, which is not replicated, to a replicated database.local

renameCollection 适合生产 环境:

  • renameCollection操作会阻塞整个数据库的活动,直到操作完成为止。
  • renameCollection不兼容分片集合(sharded collections)
  • 如果要重命名的集合名字已经存在,并且没有指定.targetdropTarget: true,renameCollection操作会失败。
  • 不能将一个来自有副本的数据库(replicated database)的集合重命名到没有副本的数据库(non-replicated database)。
  • 不能将一个来自没有副本的数据库的集合重命名到有副本的数据库。

注意事项:

  1. 相当于是一个copy的操作,如果集合数据量过大,非常耗时,线上慎用;
  2. 重名过程会阻塞整个数据库的活动,直到操作完成为止;
  3. 分片集合不支持重命名操作;

MongoDB 3.6 版本

Sharded Collections

renameCollection is not compatible with sharded collections.

Existing Target Collection

renameCollection fails if is the name of an existing collection and you do not specify .targetdropTarget: true

Performance

Changed in version 3.6.

renameCollection has different performance implications depending on the target namespace.

If the target database is the same as the source database, renameCollection simply changes the namespace. This is a quick operation.

If the target database differs from the source database, renameCollection copies all documents from the source collection to the target collection. Depending on the size of the collection, this may take longer to complete. Other operations which require exclusive access to the affected databases will be blocked until the rename completes. See What locks are taken by some common client operations? for operations which require exclusive access to all databases.

  1. 分片集合不兼容:renameCollection 操作不兼容于分片集合。这意味着,如果你的集合是分片的,你不能使用 renameCollection 来重命名这个集合。在对分片集合进行操作时,需要使用其他方式来管理集合的名称或结构。
  2. 现有目标集合:如果目标集合已经存在,并且你没有明确指定 .targetdrop 选项为 true,那么 renameCollection 操作将失败。在执行 renameCollection 操作时,如果目标集合已经存在,你必须明确指定是否要删除目标集合并覆盖它。
  3. 性能影响:在 MongoDB 3.6 版本中,renameCollection 操作的性能取决于目标命名空间的情况:

  • 如果目标数据库与源数据库相同,那么 renameCollection 操作只是简单地更改命名空间。这是一个快速的操作,因为它只涉及更改命名空间的元数据信息。
  • 如果目标数据库与源数据库不同,那么 renameCollection 操作将会复制源集合中的所有文档到目标集合中。这可能会导致操作需要花费更多的时间来完成,特别是对于大型集合来说。在执行复制操作期间,其他需要对受影响的数据库进行排他性访问的操作将被阻塞,直到重命名操作完成。

注意事项:

db.adminCommand( { renameCollection: "db1.orders", to: "db1.orders2014" } )  

  1. renameCollection 操作不兼容于分片集合;
  2. 只更改命名空间,速度极快;

db.adminCommand( { renameCollection: "db1.orders", to: "db2.orders2014" } )  

  1. 跨库重命名相当于是一个copy操作,如果集合数据量较大,执行特别耗时,阻塞操作,线上慎用。

MongoDB 4.2 版本

Sharded Collections

renameCollection is not compatible with sharded collections.

Existing Target Collection

renameCollection fails if is the name of an existing collection and you do not specify .targetdropTarget: true

Performance

Changed in version 3.6.

renameCollection has different performance implications depending on the target namespace.

If the target database is the same as the source database, renameCollection simply changes the namespace. This is a quick operation.

If the target database differs from the source database, renameCollection copies all documents from the source collection to the target collection. Depending on the size of the collection, this may take longer to complete.

Resource Locking

Changed in version 4.2.

If renaming a collection within the same database, renameCollection obtains an exclusive lock on the source and target collections for the duration of the operation. All subsequent operations on the collections must wait until renameCollection completes.

Prior to MongoDB 4.2, renaming a collection within the same database with renameCollection required an exclusive database lock.

If renaming a collection between different databases, renameCollection locking behavior depends on the MongoDB version:

For MongoDB 4.2.2 and later, renameCollection obtains an exclusive (W) lock on the target database, an intent shared (r) lock on the source database, and a shared (S) lock on the source collection. Subsequent operations on the target database must wait until renameCollection releases the exclusive database lock.

For MongoDB 4.2.1 and earlier, renameCollection obtains an exclusive (W) global lock. Subsequent operations on the mongod must wait until renameCollection releases the global lock.

For more information on locking in MongoDB, see FAQ: Concurrency.

1、分片集合不兼容:

renameCollection 操作不兼容于分片集合。这意味着无法直接对分片集合使用 renameCollection 来重命名。

2、现有目标集合:

如果要重命名的目标集合名称已经存在,并且没有指定 .targetdrop: true 参数,renameCollection 操作将失败。这是为了避免意外覆盖已存在的集合。在执行 renameCollection 操作时,需要明确指定是否要删除已存在的目标集合以便重命名成功。

3、性能:

在 MongoDB 3.6 及更高版本中,renameCollection 操作的性能取决于目标命名空间的不同情况:

  • 如果目标数据库与源数据库相同,renameCollection 操作只是简单地更改命名空间,这是一个快速的操作,因为它只涉及元数据的更改。
  • 如果目标数据库与源数据库不同,renameCollection 操作将会复制源集合中的所有文档到目标集合中。这可能会导致操作耗时更长,特别是对于大型集合而言。

4、资源锁定:

在 MongoDB 4.2 版本中,renameCollection 操作的资源锁定行为发生了变化:

  • 如果在同一数据库中重命名集合,renameCollection 会在操作期间对源集合和目标集合获取独占锁。所有对这些集合的后续操作必须等待 renameCollection 完成。
  • 在不同数据库之间重命名集合时,renameCollection 的锁定行为取决于 MongoDB 版本:
  • 对于 MongoDB 4.2.2 及更高版本,renameCollection 会在目标数据库上获取独占锁(W),在源数据库上获取意图共享锁(r),在源集合上获取共享锁(S)。所有对目标数据库的后续操作必须等待 renameCollection 释放独占数据库锁。
  • 对于 MongoDB 4.2.1 及更早版本,renameCollection 会获取全局独占锁(W)。所有对 MongoDB 实例的后续操作必须等待 renameCollection 释放全局锁。

注意事项:

db.adminCommand( { renameCollection: "db1.orders", to: "db1.orders2014" } )  

  1. renameCollection 操作不兼容于分片集合;
  2. 只更改命名空间,速度极快;
  3. 对源集合和目标集合获取独占锁,必须等待 renameCollection 完成

db.adminCommand( { renameCollection: "db1.orders", to: "db2.orders2014" } )  

  1.  MongoDB 4.2.2 及更高版本,跨库重命名相当于是一个copy操作,如果集合数据量较大,执行特别耗时,目标数据库上获取独占锁(W),目标数据库的后续操作必须等待 renameCollection 释放独占数据库锁,线上慎用。
  2. MongoDB 4.2.1 及更早版本,跨库重命名相当于是一个copy操作,如果集合数据量较大,执行特别耗时,renameCollection 会获取全局独占锁(W)。所有对 MongoDB 实例的后续操作必须等待 renameCollection 释放全局锁,线上慎用。

MongoDB 5.0 版本

Sharded Collections

Starting in MongoDB 5.0, you can use the renameCollection command to change the name of a sharded collection. The target database must be the same as the source database.

Unsharded Collections

You can use renameCollection to rename an unsharded collection in a sharded cluster as long as the source and target databases are on the same primary shard.

Existing Target Collection

renameCollection fails if target is the name of an existing collection and you do not specify dropTarget: true.

Performance

Changed in version 3.6.

renameCollection has different performance implications depending on the target namespace.

If the target database is the same as the source database, renameCollection simply changes the namespace. This is a quick operation.

If the target database differs from the source database, renameCollection copies all documents from the source collection to the target collection. Depending on the size of the collection, this may take longer to complete.

Resource Locking in Sharded Clusters

Changed in version 5.0.

When renaming a sharded or unsharded collection in a sharded cluster, the source and target collections are exclusively locked on every shard. Subsequent operations on the source and target collections must wait until the rename operation completes.

For more information on locking in MongoDB, see FAQ: Concurrency.

Resource Locking in Replica Sets

If renaming a collection within the same database, renameCollection obtains an exclusive lock on the source and target collections for the duration of the operation. All subsequent operations on the collections must wait until renameCollection completes.

If renaming a collection between different databases, renameCollection obtains an exclusive (W) lock on the target database, an intent shared (r) lock on the source database, and a shared (S) lock on the source collection. Subsequent operations on the target database must wait until renameCollection releases the exclusive database lock.

For more information on locking in MongoDB, see FAQ: Concurrency.

1、行为

  • 对于分片集合(Sharded Collections):从MongoDB 5.0开始,可以使用renameCollection命令来更改分片集合的名称。目标数据库必须与源数据库相同。
  • 对于非分片集合(Unsharded Collections):在分片集群中,只要源数据库和目标数据库在同一个主分片上,就可以使用renameCollection来重命名非分片集合。
  • 对于已存在的目标集合:如果目标集合已经存在,而且没有设置dropTarget: true选项,则renameCollection操作将失败。

2、性能:

  • 自MongoDB 3.6版本开始,renameCollection的性能取决于目标命名空间。
  • 如果目标数据库与源数据库相同,则renameCollection仅仅修改命名空间,这是一个快速的操作。
  • 如果目标数据库与源数据库不同,则renameCollection将所有文档从源集合复制到目标集合。根据集合的大小,这可能需要更长的时间来完成。

3、资源锁定:

  • 在分片集群中,当重命名分片集合或非分片集合时,每个分片上的源和目标集合都会被独占锁定。在重命名操作完成之前,对源和目标集合的后续操作必须等待。
  • 在副本集中,如果在同一个数据库中重命名集合,renameCollection会为操作的整个过程获取源和目标集合的独占锁。所有对集合的后续操作必须等待renameCollection完成。
  • 如果在不同的数据库之间重命名集合,renameCollection会在目标数据库上获取独占锁(W),在源数据库上获取意向共享锁(r),在源集合上获取共享锁(S)。后续对目标数据库的操作必须等待renameCollection释放独占数据库锁。

注意事项:

  1. 不能使用 renameCollection 重命名时间序列集合
  2. 支持分片集合renameCollection操作,不能跨库操作;
  3. 非分片集合renameCollection操作,在分片集群中,源数据库和目标数据库在同一个主分片上;

db.adminCommand( { renameCollection: "db1.orders", to: "db1.orders2014" } )  

  1. 同库重命名,只更改命名空间,速度极快;
  2. 在分片集群中,当重命名分片集合或非分片集合时,在重命名操作完成之前,源和目标集合都会被独占锁定,必须等待;
  3. 在副本集中,如果在同一个数据库中重命名集合,在重命名操作完成之前,源和目标集合都会被独占锁定,必须等待;

db.adminCommand( { renameCollection: "db1.orders", to: "db2.orders2014" } )  

跨库重命名相当于是一个copy操作,如果集合数据量较大,执行特别耗时。目标数据库上获取独占锁(W),在源数据库上获取意向共享锁(r),在源集合上获取共享锁(S)。后续对目标数据库的操作必须等待renameCollection释放独占数据库锁阻塞操作,线上慎用。

MongoDB 6.0 、7.0版本版本renameCollection未做变更

结论:

在进行 renameCollection 操作时,请务必谨慎操作。这个操作可能会对线上系统产生重大影响,因此建议在非高峰时段进行,并且提前备份数据以防万一。谨慎的操作是确保系统稳定性和数据完整性的重要步骤,我们始终致力于提供最佳的服务和解决方案,以确保您的业务顺利运行。再次感谢您对我们的信任和支持。

责任编辑:武晓燕 来源: DBA实战
相关推荐

2012-11-16 10:14:54

Windows 8

2024-06-17 10:45:07

C++编程操作符

2024-03-11 15:32:50

C++开发

2023-11-26 18:02:00

ReactDOM

2020-11-05 08:56:19

Python

2020-12-26 16:51:12

Python操作符开发

2024-05-06 00:00:00

C#工具代码

2010-09-26 10:13:25

2010-07-13 14:26:11

Perl数组

2024-10-15 16:53:07

2024-12-06 10:43:27

2023-10-23 12:35:36

Golang追加操作

2023-08-07 08:13:41

2023-11-29 09:00:55

ReactuseMemo

2023-05-05 18:33:15

2024-07-01 08:04:38

2009-02-20 09:50:29

C#方法重载编程

2024-04-30 00:00:00

数仓维度建模

2024-11-20 15:55:57

线程Java开发

2010-08-13 11:10:07

Flex.NETWebService
点赞
收藏

51CTO技术栈公众号