本文介绍MongoDB 3.4版本的兼容性变化。
如需查看MongoDB官网兼容性更新说明文档,请前往MongoDB官网下载。
分片集群变更说明
明确成员角色
在 3.4分片集群中,所有分片节点的 mongod
实例必须通过以下方式显式声明其角色为 shardsvr
:
配置文件:设置
sharding.clusterRole: shardsvr
。命令行参数:使用
--shardsvr
选项。
shardsvr
角色的 mongod
实例默认端口为 27018。若需使用其他端口,需通过 net.port
配置项或 --port
参数指定。
兼容性限制
3.4版本 mongos
无法连接早于3.4版本的 mongod
实例。
移除的配置选项
MongoDB 3.4 从 mongos
中移除了以下配置选项:
分片块大小配置:
配置文件项
sharding.chunkSize
。命令行选项
--chunkSize
。
自动分块拆分配置:
配置文件项
sharding.autoSplit
。命令行选项
--noAutoSplit
。
停止支持SCCC配置服务器
自MongoDB 3.4版本起,分片集群不再支持镜像模式(SCCC)的 mongod
实例作为配置服务器(该模式已在3.2版本标记为弃用)。
您必须将配置服务器(CSRS)部署为副本集。升级要求如下:
若需将分片集群升级至3.4版本,配置服务器必须运行为副本集。
若当前使用SCCC配置服务器,需先转换为副本集模式。
初始同步与重命名集合的兼容性问题
若在初始同步(initial sync)过程中对同步源(sync source)的集合执行重命名操作,初始同步进程将失败并重新启动,以避免潜在的数据损坏风险。具体介绍,请参见SERVER-26117。
涉及集合重命名的操作包括:
renameCollection
命令:如db.collection.renameCollection()
方法。聚合操作中的
$out
阶段:使用db.collection.aggregate()
方法或aggregate
命令时包含$out
阶段。MapReduce 的
out
选项:使用db.collection.mapReduce()
方法或mapReduce
命令时指定out
选项。convertToCapped
命令:将普通集合转换为固定集合(capped collection)。
从3.2.11或更早版本升级至 3.4时,如果初始同步过程中遇到集合重命名操作,同步可能失败。
从3.2.11及之前版本中,当遇到可能损坏数据的renameCollection操作时,初始同步过程将继续进行。具体介绍,请参见SERVER-4941。
弃用的操作说明
group
命令
自MongoDB 3.4版本起,弃用group
命令和mongo Shell的db.collection.group()
方法,请改用db.collection.aggregate()
或db.collection.mapReduce()
。
聚合命令必须指定游标
自MongoDB 3.6版本起,aggregate
命令必须通过cursor
选项返回游标,除非同时指定explain
选项用于分析执行计划。
要指示具有默认批大小的游标,请指定游标:
{}
。要指示具有非默认批大小的游标,请使用
cursor: { batchSize: <num> }
。
集合与索引规范
集合选项校验
自MongoDB 3.4起,在 create
命令及 db.createCollection()
操作中,对集合选项的校验更为严格,您必须使用 create
或 db.createCollection()
支持的合法选项。
例如,以下操作因包含无效选项 cappedtypo
导致不再合法:
db.createCollection( "myCappedCollection", { cappedtypo: true, size: 5242880 } )
索引规范校验
自MongoDB 3.4版本起,createIndexes
命令及 db.collection.createIndex()
方法在创建索引时执行更严格的校验(不适用于已有索引)。具体规则如下:
索引键模式
key: value
中的value
必须为以下值之一:值
说明
数值 > 0
升序索引(ascending)
数值 < 0
降序索引(descending)
字符串
特殊索引类型,仅允许:"text"、"2dsphere"、"2d"、"hashed"
例如,以下操作将不再有效:
db.collection.createIndex( { x: 0 } ); db.collection.createIndex( { y: "text2d" } ); db.collection.createIndex( { z: NaN } ); db.collection.createIndex( { x: 1, unique: true } )
3.4之前的版本会忽略无效的索引选项,而MongoDB 3.4版本起会直接报错。例如,以下操作将不再有效:
db.collection.createIndex( { y: 1 }, { uniques2: true} ); db.collection.createIndex( { z: 1 }, { expireAfterSec: 350 } )
通用兼容性变更说明
命名空间限制调整:自MongoDB 3.4起,数据库名称不再支持包含
$
符号。说明升级至3.4前,必须删除所有名称包含
$
的数据库。删除
textSearchEnabled
参数。MongoDB已于2.6版本默认启用文本搜索功能。移除
mongosniff
工具:自MongoDB 3.4版本起,使用功能更强大的mongoreplay
替代mongosniff
,支持更灵活的网络流量捕获与分析。聚合
$project
阶段行为变更:若$project
阶段返回空文档(未保留或新增任何字段),将触发错误。hint()
与稀疏索引的计数问题:当使用hint()
强制指定稀疏索引(sparse index) 并执行全集合文档计数(即查询条件为空)时,稀疏索引可能导致计数结果不准确。db.collection.insert({ _id: 1, y: 1 } ); db.collection.createIndex( { x: 1 }, { sparse: true } ); db.collection.find().hint( { x: 1 } ).count();
若要获得正确的计数,请不要在
hint()
中指定使用稀疏索引计数全集合文档。db.collection.find().count(); db.collection.createIndex({ y: 1 }); db.collection.find().hint({ y: 1 }).count();
在3.4之前的版本中,若使用稀疏索引会导致计数缺失,3.4之前的版本会忽略
hint()
强制索引的指定。
用户角色权限变更说明
自MongoDB 3.4起,以下内置角色的权限不再适用于 local
和 config
数据库:
角色名称 | 说明 |
readAnyDatabase | 若需授予对 local 数据库的读权限,需在 admin 库中创建用户并显式分配 local 库的 read 角色。另可通过 clusterManager 或 clusterMonitor 角色访问 config 和 local 库。 |
readWriteAnyDatabase | 若需授予对 local 数据库的读写权限,需在 admin 库中创建用户并显式分配 local 库的 readWrite 角色。 |
userAdminAnyDatabase | 无 |
dbAdminAnyDatabase | 若需授予对 local 数据库的管理权限,需在 admin 库中创建用户并显式分配 local 库的 dbAdmin 角色。 |
以下内置角色新增了对 local
和 config
数据库的权限:
clusterManager
clusterMonitor
backup
restore
不向后兼容的功能说明
MongoDB 3.4 引入了以下特性,这些特性会持久化3.4之前的版本无法正确处理的数据,您需将 featureCompatibilityVersion
设为"3.4"
方可启用:
视图(Views)
排序规则与大小写不敏感索引(Collation & Case-Insensitive Indexes)
十进制类型(Decimal Type)
索引版本 v2
新增支持了排序规则与十进制数据类型。
当
featureCompatibilityVersion
设为 "3.4" 时,新创建的索引默认版本为 v2;否则为 v1。
启用这些不兼容特性会增加降级难度。
建议在升级后,允许部署在未启用这些功能的情况下运行,以确保降级的可能性最小。当您确信降级的可能性极小时,再启用这些功能。
featureCompatibilityVersion
默认值如下:
全新部署的3.4:"3.4"。
从3.2升级的部署:"3.2"(需手动设为"3.4")。
在3.4之前的版本中,若数据库包含视图、排序规则定义或v2索引,3.4之前的版本MongoDB将无法启动;若存在十进制类型字段,针对这些文档的操作可能失败。
如需升级,您必须清除所有不兼容数据(如视图、v2索引、十进制字段)。
驱动兼容性变更说明
若要使用 MongoDB 3.4 引入的新功能(如十进制类型(Decimal Type)和排序规则(Collation)),必须将驱动程序升级至支持这些特性的版本。
单元素$in与upsert的行为变更
当 upsert
操作未找到匹配文档时,会根据查询条件中的等式语句创建基础文档,再应用更新操作符。示例如下:
db.c.drop()
db.c.update( { a : 3, b: "foo" }, { $set : { c : 15 } }, { upsert : true } )
db.c.find()
{ "_id" : ObjectId("59c03009529946822d0afb8c"), "a" : 3, "b" : "foo", "c" : 15 }
在3.4之前的版本中,单元素 $in
查询不会初始化字段:
db.c.drop()
db.c.update( { a : { $in : [1] } }, { $addToSet : { a : 2 } }, { upsert : true } )
db.c.find()
{ "_id" : ObjectId("58bdb00eb39e8f87607e9222"), "a" : [ 2 ] }
在3.4及之后版本中,单元素 $in
视为等式条件:
若查询条件中包含单元素
$in
,字段会被初始化为标量值而非数组。上述示例的
$addToSet
操作将失败,因为无法对标量字段应用数组操作符。
解决方案:将 $in
表达式包裹在 $elemMatch
中,强制保持字段的数组类型。
db.c.drop()
db.c.update(
{ a : { $elemMatch : { $in : [ 2 ] } } },
{ $addToSet : { a: 3 } },
{ upsert: true } )
db.c.find()
{ "_id" : ObjectId("..."), "a" : [ 3 ] }