mongodb4.0学习总结四(Read Isolation, Consistency, and Recency)

隔离性保证

读未提交

(对传统关系型数据,读未提交是4个隔离级别中最低的,即一个事务可以读到另外一个事务未提交的数据,以下是官网对mongodb读未提交隔离级别的说明,本人理解的不是很透。个人理解是对于mongodb来说,如果没开事务,则可以读到未持久化的数据,而对于开了多文档事务的写操作,在提交了事务前,读不到事务中改变的数据,但是在提交后,在事务未被其它客户端成员确认之前,就可以读到写入的数据)

依据read concern,客户端可以在写入持久(For a single mongod server, a write operation is considered durable when it has been written to the server’s journal file. For a replica set, a write operation is considered durable once the write operation is durable on a majority of voting nodes)之前查看写入结果:

  • 无论哪个write concern,使用"local"或"available"read concern的客户端可以在写操作被客户端确认之前看到写操作的结果。对于在多文档事务的操作,在事务中对数据的改变在事务提交前对外时不可见的,然而,其它客户端可以在事务提交了,但还未被客户端确认提交成功之前看到数据。
  • 使用"local"或"available"的read concern的客户端可能会读到之后被回滚的数据(什么情况下会回滚:https://docs.mongodb.com/manual/core/replica-set-rollbacks/

读未提交是mongodb单实例或副本集群或分片集群的默认隔离级别

读未提交和单文档原子性

写操作对于单个文档是原子的; 即,如果写入正在更新文档中的多个字段,则读取操作将永远不会看到仅更新了一些字段的文档。然而,尽管客户端可能不会读到部分跟新的文档,但是读未提交意味着并发的读操作仍然可能在更新的数据持久化之前读到更新的文档。(mongodb的数据持久化是理解这部分内容时需要理解的概念)

对于独立的mongod实例,对单个文档的一组读写操作是序列化的。对于副本集只有在没有回滚的情况下,一组对单个文档的读写操作时序列化的。

读未提交和多文档写操作

(对于传统的关系型数据库,Serializable是最高的隔离级别)

当一个写操作改变多个文档时,对单个文档的改变是原子性的,但是整个操作不是原子性的。

当执行多文档写入操作时,无论是通过单个写入操作还是多个写入操作,其他操作都可以交错。

从版本4.0开始,对于需要更新多个文档具有原子性或读取多个文档时保证一致性的情况,MongoDB为副本集提供多文档事务。

在对多个文档写操作没有隔离的时候,MongoDB表现出以下行为:

1.非即时读取操作。假设读取操作在时间t1开始并开始读取文档。然后,写入操作在稍后的某个时间t2对其中一个文档进行更新。读者可能会看到文档的更新版本,因此看不到数据的时间点快照。(可以理解为传统数据库中的脏读)

2.没有序列化的操作。比如有时要求先读后写,有时要求先写后读。

 

单调写保证

对Mongodb单独实体和副本集,提供单调写保证

Real Time Order

For read and write operations on the primary, issuing read operations with "linearizable" read concern and write operations with "majority" write concern enables multiple threads to perform reads and writes on a single document as if a single thread performed these operations in real time; that is, the corresponding schedule for these reads and writes is considered linearizable.

对与在primary节点的读和写操作,"linearizable"read concern和"majority"write concern使得多个线程对单个文档执行的写和读操作就像单个线程一样,也就是,对那些读和写的进程是线性化的。

 

因果一致性

如果一个操作依赖与前一个的操作,则这些操作之间存在因果关系,在因果一致性session中,mongodb按顺序执行操作,并且客户端得到的结果具有一致性。

客户端session和因果一致性保证

为了提供因果一致性,MongoDB 3.6支持客户端会话中的因果一致性。因果一致性的会话意味着具有"majority"read concern的读操作和具有"majority"write concern的写操作的按顺序执行(详情参考:https://docs.mongodb.com/manual/core/causal-consistency-read-write-concerns/)。必须确保在一个客户端session中在同一时间只有一个线程执行这些操作。

操作详情:

1.客户端开启一个客户端session
    注意:只有在下面两个情况都满足的情况下才保证因果一致性:

  • Read operations with "majority"; i.e. the return data has been acknowledged by a majority of the replica set members and is durable.
  • Write operations with "majority" write concern; i.e. the write operations that request acknowledgement that the operation has been applied to a majority of the replica set’s voting members.

2.客户端session发出一系列读和写操作,session的信息伴随每个操作;

3.对每个与session关联的操作,mongodb都会返回操作时间和集群时间,即使操作失败。

4.相关的客户端session跟随两个时间字段。

因果一致性保证

下表提供了当read concern和write concern都为"majority"时提供的因果一致性保证:

GuaranteesDescription
Read your writesRead operations reflect the results of write operations that precede them.
Monotonic reads

Read operations do not return results that correspond to an earlier state of the data than a preceding read operation.

For example, if in a session:

  • write1 precedes write2,
  • read1 precedes read2, and
  • read1 returns results that reflect write2

then read2 cannot return results of write1.

Monotonic writes

Write operations that must precede other writes are executed before those other writes.

For example, if write1 must precede write2 in a session, the state of the data at the time of write2must reflect the state of the data post write1. Other writes can interleave between write1 and write write2, but write2 cannot occur before write1.

Writes follow readsWrite operations that must occur after read operations are executed after those read operations. That is, the state of the data at the time of the write must incorporate the state of the data of the preceding read operations.

 

Read Preference

因果一致性保证支持所有成员。比如在一个session中,先执行了"majority”write concern的写操作,接着"majority" read concern读了secondary,则结果会返回写操作之后的结果。

隔离性

会话中的操作与会话外的操作是没有隔离性的,如果一个并发的写操作发生在一个会话的写和读操作之间,则读操作返回的是外部写操作之后的结果。

 

EXAMPLES:

例子展示在test集合中先更新在插入。

/ Example 1: Use a causally consistent session to ensure that the update occurs before the insert.
ClientSession session1 = client.startSession(ClientSessionOptions.builder().causallyConsistent(true).build());
Date currentDate = new Date();
MongoCollection<Document> items = client.getDatabase("test")
        .withReadConcern(ReadConcern.MAJORITY)
        .withWriteConcern(WriteConcern.MAJORITY.withWTimeout(1000, TimeUnit.MILLISECONDS))
        .getCollection("test");

items.updateOne(session1, eq("sku", "111"), set("end", currentDate));

Document document = new Document("sku", "nuts-111")
        .append("name", "Pecans")
        .append("start", currentDate);
items.insertOne(session1, document);

如果另一个客户端需要读取所有当前sku值,则可以将集群时间和操作时间提前到另一个会话的时间,以确保此客户端与其他会话在因果关系上一致并在两次写入后读取:

/ Example 2: Advance the cluster time and the operation time to that of the other session to ensure that
// this client is causally consistent with the other session and read after the two writes.
ClientSession session2 = client.startSession(ClientSessionOptions.builder().causallyConsistent(true).build());
session2.advanceClusterTime(session1.getClusterTime());
session2.advanceOperationTime(session1.getOperationTime());

items = client.getDatabase("test")
        .withReadPreference(ReadPreference.secondary())
        .withReadConcern(ReadConcern.MAJORITY)
        .withWriteConcern(WriteConcern.MAJORITY.withWTimeout(1000, TimeUnit.MILLISECONDS))
        .getCollection("items");

for (Document item: items.find(session2, eq("end", BsonNull.VALUE))) {
    System.out.println(item);
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值