Causal Consistency and Read and Write Concerns
With MongoDB's causally consistent client sessions, different combinations of read and write concerns provide different causal consistency guarantees. When causal consistency is defined to imply durability, then the following table lists the specific guarantees provided by the various combinations:
Read Concern | Write Concern | Read own writes | Monotonic reads | Monotonic writes | Writes follow reads |
---|---|---|---|---|---|
✅ | ✅ | ✅ | ✅ | ||
✅ | ✅ | ||||
✅ |
If causal consistency implies durability, then, as seen from the table,
only read operations with "majority"
read concern and
write operations with "majority"
write concern can
guarantee all four causal consistency guarantees. That is,
causally consistent client sessions can only
guarantee causal consistency for:
Read operations with
"majority"
read concern; i.e. the read operations that return data that 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.
If causal consistency does not imply durability (i.e. writes may be
rolled back), then write operations with { w: 1 }
write concern can also provide causal consistency.
Note
The other combinations of read and write concerns may also satisfy all four causal consistency guarantees in some situations, but not necessarily in all situations.
The read concern "majority"
and write concern
"majority"
ensure that the four causal consistency
guarantees hold even in circumstances (such as with a network
partition) where two members in a replica set
transiently believe that they are the primary. And while both
primaries can complete writes with { w: 1 }
write concern, only one primary will be able to complete
writes with "majority"
write concern.
For example, consider a situation where a network partition divides a five member replica set:
Example
With the above partition
Writes with
"majority"
write concern can complete onP
new but cannot complete onP
old.Writes with
{ w: 1 }
write concern can complete on eitherP
old orP
new. However, the writes toP
old (as well as the writes replicated toS
1) roll back once these members regain communication with the rest of the replica set.After a successful write with
"majority"
write concern onP
new, causally consistent reads with"majority"
read concern can observe the write onP
new,S
2,andS
3. The reads can also observe the write onP
old andS
1 once they can communicate with the rest of the replica set and sync from the other members of the replica set. Any writes made toP
old and/or replicated toS
1 during the partition are rolled back.
Scenarios
To illustrate the read and write concern requirements, the following scenarios have a client issue a sequence of operations with various combination of read and write concerns to the replica set:
Read Concern "majority"
and Write concern "majority"
The use of read concern "majority"
and write concern
"majority"
in a causally consistent session provides
the following causal consistency guarantees:
✅ Read own writes ✅ Monotonic reads ✅ Monotonic writes ✅ Writes follow reads
Note
Scenario 1 (Read Concern "majority" and Write Concern "majority")
During the transient period with two primaries, because only P
new can fulfill writes with { w: "majority" }
write concern, a client session can issue the
following sequence of operations successfully:
Sequence | Example |
---|---|
1. Write 1 with write concern "majority" to P new2. Read 1 with read concern "majority" to S 23. Write 2 with write concern "majority" to P new4. Read 2 with read concern "majority" to S 3 | For item A , update qty to 50 .Read item A .For items with qty less than or equal to 50 ,update restock to true .Read item A . |
✅ Read own writes | Read 1 reads data from S 2 that reflects a state after Write 1.Read 2 reads data from S 3 that
reflects a state after Write 1 followed by Write
2. |
✅ Monotonic reads | Read 2 reads data from S 3 that reflects
a state after Read 1. |
✅ Monotonic writes | Write 2 updates data on P new that
reflects a state after Write 1. |
✅ Writes follow reads | Write 2 updates data on P new that
reflects a state of the data after Read 1 (i.e. an
earlier state reflects the data read by Read 1). |
Note
Scenario 2 (Read Concern "majority" and Write Concern "majority")
Consider an alternative sequence where Read 1 with read
concern "majority"
routes to S
1:
Sequence | Example |
---|---|
1. Write 1 with write concern "majority" to P new2. Read 1 with read concern "majority" to S 13. Write 2 with write concern "majority" to P new4. Read 2 with with read concern "majority" to S 3 | For item A , update qty to 50 .Read item A .For items with qty less than or equal to 50 ,update restock to true .Read item A . |
In this sequence, Read 1 cannot return until the
majority commit point has advanced on P
old. This cannot
occur until P
old and S
1 can communicate
with the rest of the replica set; at which time, P
old
has stepped down (if not already), and the two members sync
(including Write 1) from the other members of the
replica set.
✅ Read own writes | Read 1 reflects a state of data after Write1
1, albeit after the network partition has healed
and the member has sync'ed from the other members of the
replica set. Read 2 reads data from S 3 that
reflects a state after Write1 1 followed by Write
2. |
✅ Monotonic reads | Read 2 reads data from S 3 that reflects
a state after Read 1 (i.e. an earlier state is
reflected in the data read by Read 1). |
✅ Monotonic writes | Write 2 updates data on P new that
reflects a state after Write 1. |
✅ Writes follow reads | Write 2 updates data on P new that
reflects a state of the data after Read 1 (i.e. an
earlier state reflects the data read by Read 1). |
Read Concern "majority"
and Write concern {w: 1}
The use of read concern "majority"
and write concern
{ w: 1 }
in a causally consistent session
provides the following causal consistency guarantees if causal consistency implies durability:
❌ Read own writes ✅ Monotonic reads ❌ Monotonic writes ✅ Writes follow reads
If causal consistency does not imply durability:
✅ Read own writes ✅ Monotonic reads ✅ Monotonic writes ✅ Writes follow reads
Note
Scenario 3 (Read Concern "majority" and Write Concern {w: 1})
During the transient period with two primaries, because both P
old and P
new can fulfill writes with
{ w: 1 }
write concern, a client session
could issue the following sequence of operations
successfully but not be causally consistent if causal consistency
implies durability:
Sequence | Example |
---|---|
1. Write 1 with write concern { w: 1 } to P old2. Read 1 with read concern "majority" to S 23. Write 2 with write concern { w: 1 } to P new4. Read 2 with with read concern "majority" to S 3 | For item A , update qty to 50 .Read item A .For items with qty less than or equal to 50 ,update restock to true .Read item A . |
In this sequence,
Read 1 cannot return until the majority commit point has advanced on
P
new past the time of Write 1.Read 2 cannot return until the majority commit point has advanced on
P
new past the time of Write 2.Write 1 will roll back when the network partition is healed.
➤ If causal consistency implies durability
❌ Read own writes | Read 1 reads data from S 2 that does not
reflect a state after Write 1. |
✅ Monotonic reads | Read 2 reads data from S 3 that reflects
a state after Read 1 (i.e. an earlier state is
reflected in the data read by Read 1). |
❌ Monotonic writes | Write 2 updates data on P new that does
not reflect a state after Write 1. |
✅ Writes follow reads | Write 2 updates data on P new that
reflects a state after Read 1 (i.e. an
earlier state reflects the data read by Read
1). |
➤ If causal consistency does not imply durability
✅ Read own writes | Read 1 reads data from S 2 returns data
that reflects a state equivalent to Write 1 followed
by rollback of Write 1. |
✅ Monotonic reads | Read 2 reads data from S 3 that reflects
a state after Read 1 (i.e. an earlier state is
reflected in the data read by Read 1). |
✅ Monotonic writes | Write 2 updates data on P new that is
equivalent to after Write 1 followed by rollback of Write
1. |
✅ Writes follow reads | Write 2 updates data on P new that
reflects a state after Read 1 (i.e. whose
earlier state reflects the data read by Read
1). |
Note
Scenario 4 (Read Concern "majority" and Write Concern {w: 1})
Consider an alternative sequence where Read 1 with
read concern "majority"
routes to S
1:
Sequence | Example |
---|---|
1. Write 1 with write concern { w: 1 } to P old2. Read 1 with read concern "majority" to S 13. Write 2 with write concern { w: 1 } to P new4. Read 2 with with read concern "majority" to S 3 | For item A , update qty to 50 .Read item A .For items with qty less than or equal to 50 ,update restock to true .Read item A . |
In this sequence:
Read 1 cannot return until the majority commit point has advanced on
S
1. This cannot occur untilP
old andS
1 can communicate with the rest of the replica set. At which time,P
old has stepped down (if not already), Write 1 is rolled back fromP
old andS
1, and the two members sync from the other members of the replica set.
➤ If causal consistency implies durability
❌ Read own writes | The data read by Read 1 does not reflect the results
of Write 1, which has rolled back. |
✅ Monotonic reads | Read 2 reads data from S 3 that reflects
a state after Read 1 (i.e. whose
earlier state reflects the data read by Read
1). |
❌ Monotonic writes | Write 2 updates data on P new that does
not reflect a state after Write 1, which had preceded
Write 2 but has rolled back. |
✅ Writes follow reads | Write 2 updates data on P new that
reflects a state after Read 1 (i.e. whose
earlier state reflects the data read by Read 1). |
➤ If causal consistency does not imply durability
✅ Read own writes | Read 1 returns data that reflects the final result of
Write 1 since Write 1 ultimately rolls back. |
✅ Monotonic reads | Read 2 reads data from S 3 that reflects
a state after Read 1 (i.e. an earlier state
reflects the data read by Read 1). |
✅ Monotonic writes | Write 2 updates data on P new that is
equivalent to after Write 1 followed by rollback of Write
1. |
✅ Writes follow reads | Write 2 updates data on P new that
reflects a state after Read 1 (i.e. an earlier state
reflects the data read by Read 1). |
Read Concern "local"
and Write concern {w: 1}
The use of read concern "local"
and write concern
{ w: 1 }
in a causally consistent session
cannot guarantee causal consistency.
❌ Read own writes ❌ Monotonic reads ❌ Monotonic writes ❌ Writes follow reads
This combination may satisfy all four causal consistency guarantees in some situations, but not necessarily in all situations.
Note
Scenario 5 (Read Concern "local" and Write Concern {w: 1})
During this transient period, because both P
old and
P
new can fulfill writes with { w: 1 }
write concern, a
client session could issue the following sequence of operations
successfully but not be causally consistent:
Sequence | Example |
---|---|
For item A , update qty to 50 .Read item A .For items with qty less than or equal to 50 ,update restock to true .Read item A . |
❌ Read own writes | Read 2 reads data from S 3 that only
reflects a state after Write 2 and not Write 1
followed by Write 2. |
❌ Monotonic reads | Read 2 reads data from S 3 that does not
reflect a state after Read 1 (i.e. an earlier state
does not reflect the data read by Read 1). |
❌ Monotonic writes | Write 2 updates data on P new that does
not reflect a state after Write 1. |
❌ Write follow read | Write 2 updates data on P new that does
not reflect a state after Read 1 (i.e. an earlier
state does not reflect the data read by Read 1). |
Read Concern "local"
and Write concern "majority"
The use of read concern "local"
and write concern
"majority"
in a causally consistent session provides
the following causal consistency guarantees:
❌ Read own writes ❌ Monotonic reads ✅ Monotonic writes ❌ Writes follow reads
This combination may satisfy all four causal consistency guarantees in some situations, but not necessarily in all situations.
Note
Scenario 6 (Read Concern "local" and Write Concern "majority")
During this transient period, because only P
new can
fulfill writes with { w: "majority" }
write concern, a client
session could issue the following sequence of operations successfully
but not be causally consistent:
Sequence | Example |
---|---|
1. Write 1 with write concern "majority" to P new2. Read 1 with read concern "local" to S 13. Write 2 with write concern "majority" to P new4. Read 2 with read concern "local" to S 3 | For item A , update qty to 50 .Read item A .For items with qty less than or equal to 50 ,update restock to true .Read item A . |
❌ Read own writes. | Read 1 reads data from S 1 that does not
reflect a state after Write1 1. |
❌ Monotonic reads. | Read 2 reads data from S 3 that does not
reflect a state after Read 1 (i.e. an earlier state
does not reflect the data read by Read 1). |
✅ Monotonic writes | Write 2 updates data on P new that
reflects a state after Write 1. |
❌ Write follow read. | Write 2 updates data on P new that does
not reflect a state after Read 1 (i.e. an earlier
state does not reflect the data read by Read 1). |