翻译或纠错本页面

原子性和事务处理

在MongoDB中,一个写操作的原子性是基于单个文档的,即使写操作是在单个文档*内部*更改多个嵌套文档。

当一个写操作修改了多个文档,每个文档的更新是具有原子性的,但是整个操作作为一个整体是不具有原子性的,并且与其他操作可能会有所交替。但是,您可以使用:update:`$isolated`操作将多个文档单的写操作*隔离*成单个的写操作,

``$isolated``操作

使用:update:`$isolated`写操作将影响多个文档,能够阻止其它的进程在写操作的过程中修改第一个文档。这样就保证没有客户端能够看到修改,直到写操作完成或者出错。

$isolated`操作在:term: `sharded clusters 中**不**起作用。

这个隔离的写操作不提供”所有或者全部没有”的原子性。这就是说在写的过程中如果有错误产生不会将所有的在错误产生之前的更新全部回滚。

注解

:update:`$isolated`操作将使写操作在集合上获得一个排他锁,*甚至对于文档级别的锁存储引擎*比如WiredTiger也是这样处理的。这也就是说在执行:update:`$isolated`操作运行期间会导致WiredTiger单线程运行。

:update:`$isolated`操作在分片集群中**不**起作用。

使用:update:$isolated`更新操作的例子请参看:update:`$isolated$isolated 删除操作的的例子参看:ref: isolate-remove-operations

类事务处理语句

因为单个文档中可以包含嵌套文档,所以单个文档的原子性在很多实践场景下就能够满足需求。在需要多个连续的写操作必须像一个写操作那样保持原子性的场景下,您可以在应用中使用 :doc: two-phase commit </tutorial/perform-two-phase-commits>

但是,两阶段提交只能提供*类*事务处理的语句。使用两阶段提交保证了数据的一致性,但是在两阶段提交或者回滚时,应用是有可能返回中间数据的。

更多关于两阶段提交和回滚,参看:doc: /tutorial/perform-two-phase-commits

并行处理的控制

并行处理的控制允许多个应用同时运行而不会造成数据的不一致或者冲突。

一个方法是在字段上创建一个唯一性的:ref: unique index <index-type-unique> 。这样就可以阻止插入或者更新重复的数据。在多个字段上创建唯一性索引将保证多个字段组合的唯一性。使用案例参看:ref: update() and Unique Index <update-with-unique-indexes> 和 :ref: findAndModify() and Unique Index <upsert-and-unique-index>

另外一种方法是通过在写操作中使用查询断言来指定期望的字段当前值。两阶段提交模式除了提供查询断言以外还额外可以指定期望的数据写的状态ref: application identifier <2-phase-commits-concurrency>