Database Manual / CRUD Operations / CRUD Concepts

Atomicity and Transactions原子性和事务

In MongoDB, a write operation is atomic on the level of a single document, even if the operation modifies multiple values. When multiple update commands happen in parallel, each individual command ensures that the query condition still matches.在MongoDB中,写操作在单个文档级别上是原子性的,即使该操作修改了多个值。当多个更新命令并行发生时,每个单独的命令都能确保查询条件仍然匹配。

To guarantee that concurrent update commands do not conflict with each other, you can specify the expected current value of a field in the update filter.为了保证并发更新命令不会相互冲突,您可以在更新筛选器中指定字段的预期当前值。

Example示例

Consider a collection with this document:考虑一个包含此文档的集合:

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

These update operations occur concurrently:这些更新操作同时发生:

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

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

One update operation sets the document's score field to either 90 or 100. After this update completes, the second update operation no longer matches the query predicate { score: 80 }, and is not performed.一个更新操作将文档的score字段设置为90100。此更新完成后,第二次更新操作不再与查询谓词{ score: 80 }匹配,因此不会执行。

Warning

In the case of concurrent update operations, specifying a filter on a field that is not being updated can lead to unexpected results. For example, consider if these update operations occur concurrently:在并发更新操作的情况下,在未更新的字段上指定筛选器可能会导致意外结果。例如,考虑这些更新操作是否同时发生:

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

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

After one update operation completes, the remaining operation still matches the query predicate { _id: 1 }. As a result, both update operations occur and the stored score value reflects the second update operation. 在一个更新操作完成后,剩余的操作仍然与查询谓词{ _id: 1 }匹配。结果,两次更新操作都发生,并且存储的score值反映了第二次更新操作。This is problematic because the client that issued the first update does not receive any indication that the update was overwritten and the score value is different than expected.这是有问题的,因为发出第一次更新的客户端没有收到任何更新被覆盖的指示,并且score值与预期不同。

To prevent conflicting write operations when your update filter is on a different field than the one being updated, use the $inc operator.当更新筛选器位于与正在更新的字段不同的字段时,若要防止发生冲突的写入操作,请使用$inc运算符。

For example, consider if these update operations occur concurrently:例如,考虑这些更新操作是否同时发生:

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

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

After one update operation completes, the remaining operation still matches the query predicate { _id: 1 }. However, because the operations modify the current value of score, they don't overwrite each other. Both updates are reflected and the resulting score is 110.在一个更新操作完成后,剩余的操作仍然与查询谓词{ _id: 1 }匹配。但是,由于这些操作修改了score的当前值,因此它们不会相互覆盖。这两个更新都得到了反映,结果score110

Tip

Store Unique Values存储独特值

To ensure that a field only has unique values, you can create a unique index. Unique indexes prevent inserts and updates from creating duplicate data. 为了确保字段只有唯一的值,您可以创建一个唯一的索引。唯一索引可防止插入和更新创建重复数据。You can create a unique index on multiple fields to ensure the combination of field values is unique. For examples, see Create a Unique Index.您可以在多个字段上创建唯一索引,以确保字段值的组合是唯一的。有关示例,请参阅创建唯一索引

Multi-Document Transactions多文档事务

When a single write operation (e.g. db.collection.updateMany()) modifies multiple documents, the modification of each document is atomic, but the operation as a whole is not atomic.当单个写入操作(例如db.collection.updateMany())修改多个文档时,每个文档的修改都是原子性的,但整个操作不是原子性的。

When performing multi-document write operations, whether through a single write operation or multiple write operations, other operations may interleave.在执行多文档写入操作时,无论是通过单个写入操作还是多个写入操作,其他操作都可能交织在一起。

For situations that require atomicity of reads and writes to multiple documents (in a single or multiple collections), MongoDB supports distributed transactions, including transactions on replica sets and sharded clusters.对于需要对多个文档(在单个或多个集合中)进行读写原子性的情况,MongoDB支持分布式事务,包括副本集和分片集群上的事务。

For more information, see transactions有关更多信息,请参阅事务

Important

In most cases, a distributed transaction incurs a greater performance cost over single document writes, and the availability of distributed transactions should not be a replacement for effective schema design. 在大多数情况下,分布式事务比单文档写入产生更大的性能成本,分布式事务的可用性不应取代有效的模式设计。For many scenarios, the denormalized data model (embedded documents and arrays) will continue to be optimal for your data and use cases. That is, for many scenarios, modeling your data appropriately will minimize the need for distributed transactions.对于许多场景,非规范化数据模型(嵌入式文档和数组)将继续是数据和用例的最佳选择。也就是说,对于许多场景,适当地对数据进行建模将最大限度地减少对分布式事务的需求。

For additional transactions usage considerations (such as runtime limit and oplog size limit), see also Production Considerations.有关其他事务使用注意事项(如运行时限制和oplog大小限制),另请参阅生产注意事项

Learn More了解更多

Read Isolation, Consistency, and Recency读取隔离性、一致性和新近性