Docs 菜单
Docs 主页
/ /

原子性和事务

在MongoDB中,写入操作在单文档级别上具有 原子性,即使修改多个值也是如此。对于并行更新,每个命令确保查询条件仍然匹配。

为防止并发更新期间发生冲突,请在更新过滤中包含预期的当前值。

考虑包含此文档的集合:

db.games.insertOne( { _id: 1, score: 80 } )

这些更新操作会同时发生:

// Update A
db.games.updateOne(
{ score: 80 },
{
$set: { score: 90 }
}
)
// Update B
db.games.updateOne(
{ score: 80 },
{
$set: { score: 100 }
}
)

一项更新将 score 设置为 90100。随后,第二次更新无法匹配 { score: 80 },因此无法运行。

警告

在并发更新期间,筛选不更新的字段可能会导致意外结果。考虑以下操作:

// Update A
db.games.updateOne(
{ _id: 1 },
{
$set: { score: 90 }
}
)
// Update B
db.games.updateOne(
{ _id: 1 },
{
$set: { score: 100 }
}
)

两次更新均与 { _id: 1 } 匹配,因此均运行。第二次更新将覆盖第一次。第一个客户端不会收到有关其更新丢失的警告。

为避免筛选未更新字段时发生冲突,请使用$inc

示例,考虑以下并发更新操作:

// Update A
db.games.updateOne(
{ _id: 1 },
{
$inc: { score: 10 }
}
)
// Update B
db.games.updateOne(
{ _id: 1 },
{
$inc: { score: 20 }
}
)

两次更新都与 { _id: 1 } 匹配。由于它们会递增而不是设立值,因此不会相互覆盖。最后的 score110

提示

Store Unique Values

要实施唯一性,请创建唯一索引。这样可以防止插入和更新中出现重复数据。您还可以在多个字段上创建唯一索引。请参阅创建单字段唯一索引。

本节介绍多文档事务的其他详细信息。

当单个写操作(例如 db.collection.updateMany())修改了多份文档,则每份文档的修改都是原子性的,但整个操作不是原子性的。

在执行多文档写入操作时,无论是通过单次写入操作还是多次写入操作,其他操作都可能会交错进行。

对于需要对多个文档(在单个或多个集合中)原子性读取和写入的情况,MongoDB 支持分布式事务,包括副本集和分片集群上的事务。

有关详细信息,请参阅事务。

重要

在大多数情况下,与单文档写入操作相比,分布式事务会产生更高的性能成本,并且分布式事务的可用性不应取代有效的模式设计。在许多情况下,非规范化数据模型(嵌入式文档和数组)仍然是数据和使用案例的最佳选择。换言之,对于许多场景,适当的数据建模将最大限度地减少对分布式事务的需求。

有关其他事务使用注意事项(如运行时间限制和 oplog 大小限制),另请参阅生产注意事项

读取隔离性、一致性和新近度

后退

MongoDB CRUD 概念

在此页面上