From 13cac4cde2c1f2b1d93094694c5f7c85550ca124 Mon Sep 17 00:00:00 2001 From: kay Date: Mon, 13 Aug 2018 14:13:49 -0400 Subject: [PATCH] DOCS-11866, DOCS-11882: updates to causally consistent sessions --- config/sphinx_local.yaml | 1 + ...causal-consistency-read-write-concerns.txt | 609 ++++++++++++++++++ .../read-isolation-consistency-recency.txt | 236 +++++-- source/images/causal-rc-local-wc-1.svg | 95 +++ source/images/causal-rc-local-wc-majority.svg | 95 +++ source/images/causal-rc-majority-wc-1.svg | 93 +++ .../images/causal-rc-majority-wc-majority.svg | 94 +++ .../network-partition-two-primaries.svg | 61 ++ source/includes/3.6-drivers.rst | 28 +- source/reference/read-concern.txt | 10 +- source/reference/read-preference.txt | 21 +- 11 files changed, 1270 insertions(+), 73 deletions(-) create mode 100644 source/core/causal-consistency-read-write-concerns.txt create mode 100644 source/images/causal-rc-local-wc-1.svg create mode 100644 source/images/causal-rc-local-wc-majority.svg create mode 100644 source/images/causal-rc-majority-wc-1.svg create mode 100644 source/images/causal-rc-majority-wc-majority.svg create mode 100644 source/images/network-partition-two-primaries.svg diff --git a/config/sphinx_local.yaml b/config/sphinx_local.yaml index aa2ce61e36b..ad533c52308 100644 --- a/config/sphinx_local.yaml +++ b/config/sphinx_local.yaml @@ -25,6 +25,7 @@ theme: - /core/authentication - /core/authorization - /core/backups + - /core/read-isolation-consistency-recency - /core/databases-and-collections - /core/geohaystack - /core/index-single diff --git a/source/core/causal-consistency-read-write-concerns.txt b/source/core/causal-consistency-read-write-concerns.txt new file mode 100644 index 00000000000..99c798b5c80 --- /dev/null +++ b/source/core/causal-consistency-read-write-concerns.txt @@ -0,0 +1,609 @@ +============================================== +Causal Consistency and Read and Write Concerns +============================================== + +.. default-domain:: mongodb + +With MongoDB's :ref:`causally consistent client sessions `, +different combinations of read and write concerns provide different +:ref:`causal consistency guarantees `. When +causal consistency is defined to imply durability, then the following table lists +the specific guarantees provided by the various combinations: + +.. list-table:: + :header-rows: 1 + + * - Read Concern + - Write Concern + - Read own writes + - Monotonic reads + - Monotonic writes + - Writes follow reads + + * - :readconcern:`"majority"` + - :writeconcern:`"majority"` + - |checkmark| + - |checkmark| + - |checkmark| + - |checkmark| + + * - :readconcern:`"majority"` + - :writeconcern:`{ w: 1 } <\>` + - + - |checkmark| + - + - |checkmark| + + * - :readconcern:`"local"` + - :writeconcern:`{ w: 1 } <\>` + - + - + - + - + + * - :readconcern:`"local"` + - :writeconcern:`"majority"` + - + - + - |checkmark| + - + +If causal consistency implies durability, then, as seen from the table, +only read operations with :readconcern:`"majority"` read concern and +write operations with :writeconcern:`"majority"` write concern can +guarantee all four causal consistency guarantees. That is, +:ref:`causally consistent client sessions ` can only +guarantee causal consistency for: + +- Read operations with :readconcern:`"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 :writeconcern:`"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 :writeconcern:`{ 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 :readconcern:`"majority"` and write concern +:writeconcern:`"majority"` ensure that the four causal consistency +guarantees hold even in :ref:`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 :writeconcern:`{ w: 1 } +<\>` write concern, only one primary will be able to complete +writes with :writeconcern:`"majority"` write concern. + +For example, consider a situation where a network partition divides a +five member replica set: + +.. figure:: /images/network-partition-two-primaries.svg + :alt: Network partition: new primary elected on one side but old primary has not stepped down yet. + :figwidth: 240px + +.. admonition:: With the above partition + :class: admonition-example + + - Writes with :writeconcern:`"majority"` write concern can complete + on ``P``\ :sub:`new` but cannot complete on ``P``\ :sub:`old`. + + - Writes with :writeconcern:`{ w: 1 } <\>` write concern + can complete on either ``P``\ :sub:`old` or ``P``\ :sub:`new`. + However, the writes to ``P``\ :sub:`old` (as well as the writes + replicated to ``S``\ :sub:`1`) roll back once these members regain + communication with the rest of the replica set. + + - After a successful write with :writeconcern:`"majority"` write + concern on ``P``\ :sub:`new`, causally consistent reads with + :readconcern:`"majority"` read concern can observe the write on + ``P``\ :sub:`new`, ``S``\ :sub:`2`,and ``S``\ :sub:`3`. The reads + can also observe the write on ``P``\ :sub:`old` and ``S``\ + :sub:`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 to ``P``\ :sub:`old` and/or replicated to ``S``\ :sub:`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: + +- :ref:`causal-rc-majority-wc-majority` + +- :ref:`causal-rc-majority-wc-1` + +- :ref:`causal-rc-local-wc-majority` + +- :ref:`causal-rc-local-wc-1` + +.. _causal-rc-majority-wc-majority: + +Read Concern ``"majority"`` and Write concern ``"majority"`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The use of read concern :readconcern:`"majority"` and write concern +:writeconcern:`"majority"` in a causally consistent session provides +the following causal consistency guarantees: + +|checkmark| Read own writes |checkmark| Monotonic reads |checkmark| Monotonic writes |checkmark| Writes follow reads + +.. topic:: Scenario 1 (Read Concern "majority" and Write Concern "majority") + + During the transient period with two primaries, because only ``P``\ + :sub:`new` can fulfill writes with :writeconcern:`{ w: "majority" } + <"majority">` write concern, a client session can issue the + following sequence of operations successfully: + + .. list-table:: + :header-rows: 1 + :class: no-outer-border + + * - Sequence + + - Example + + * - | 1. Write\ :sub:`1` with write concern :writeconcern:`"majority"` to ``P``\ :sub:`new` + | 2. Read\ :sub:`1` with read concern :readconcern:`"majority"` to ``S``\ :sub:`2` + | 3. Write\ :sub:`2` with write concern :writeconcern:`"majority"` to ``P``\ :sub:`new` + | 4. Read\ :sub:`2` with read concern :readconcern:`"majority"` to ``S``\ :sub:`3` + + - | For item ``A``, update ``qty`` to ``50``. + | Read item ``A``. + | For items with ``qty`` less than ``50``, update ``reorder`` to ``true``. + | Read item ``A``. + + .. figure:: /images/causal-rc-majority-wc-majority.svg + :alt: State of data with two primaries using read concern majority and write concern majority + :figwidth: 550px + + .. list-table:: + :class: no-outer-border + :widths: 20 80 + + * - |checkmark| **Read own writes** + + - | Read\ :sub:`1` reads data from ``S``\ :sub:`2` that reflects a state after Write\ :sub:`1`. + | Read\ :sub:`2` reads data from ``S``\ :sub:`1` that + reflects a state after Write1\ :sub:`1` followed by Write\ + :sub:`2`. + + * - |checkmark| **Monotonic reads** + + - Read\ :sub:`2` reads data from ``S``\ :sub:`3` that reflects + a state after Read\ :sub:`1`. + + * - |checkmark| **Monotonic writes** + + - Write\ :sub:`2` updates data on ``P``\ :sub:`new` that + reflects a state after Write\ :sub:`1`. + + * - |checkmark| **Writes follow reads** + + - Write\ :sub:`2` updates data on ``P``\ :sub:`new` that + reflects a state of the data after Read\ :sub:`1` (i.e. an + earlier state reflects the data read by Read\ :sub:`1`). + +.. topic:: Scenario 2 (Read Concern "majority" and Write Concern "majority") + + Consider an alternative sequence where Read\ :sub:`1` with read + concern :readconcern:`"majority"` routes to ``S``\ :sub:`1`: + + .. list-table:: + :header-rows: 1 + :class: no-outer-border + + * - Sequence + + - Example + + + * - | 1. Write\ :sub:`1` with write concern :writeconcern:`"majority"` to ``P``\ :sub:`new` + | 2. Read\ :sub:`1` with read concern :readconcern:`"majority"` to ``S``\ :sub:`1` + | 3. Write\ :sub:`2` with write concern :writeconcern:`"majority"` to ``P``\ :sub:`new` + | 4. Read\ :sub:`2` with with read concern :readconcern:`"majority"` to ``S``\ :sub:`3` + + - | For item ``A``, update ``qty`` to ``50``. + | Read item ``A``. + | For items with ``qty`` less than ``50``, update ``reorder`` to ``true``. + | Read item ``A``. + + In this sequence, Read\ :sub:`1` cannot not return until the + majority commit point has advanced on ``P``\ :sub:`old`. This cannot + occur until ``P``\ :sub:`old` and ``S``\ :sub:`1` can communicate + with the rest of the replica set; at which time, ``P``\ :sub:`old` + has stepped down (if not already), and the two members sync + (including includes Write\ :sub:`1`) from the other members of the + replica set. + + .. list-table:: + :class: no-outer-border + :widths: 20 80 + + * - |checkmark| **Read own writes** + + - | Read\ :sub:`1` reflects a state of data after Write1\ + :sub:`1`, albeit after the network partition has healed + and the member has sync'ed from the other members of the + replica set. + + | Read\ :sub:`2` reads data from ``S``\ :sub:`3` that + reflects a state after Write1\ :sub:`1` followed by Write\ + :sub:`2`. + + * - |checkmark| **Monotonic reads** + + - Read\ :sub:`2` reads data from ``S``\ :sub:`3` that reflects + a state after Read\ :sub:`1` (i.e. an earlier state is + reflected in the data read by Read\ :sub:`1`). + + * - |checkmark| **Monotonic writes** + + - Write\ :sub:`2` updates data on ``P``\ :sub:`new` that + reflects a state after Write\ :sub:`1`. + + * - |checkmark| **Writes follow reads** + + - Write\ :sub:`2` updates data on ``P``\ :sub:`new` that + reflects a state of the data after Read\ :sub:`1` (i.e. an + earlier state reflects the data read by Read\ :sub:`1`). + +.. _causal-rc-majority-wc-1: + +Read Concern ``"majority"`` and Write concern ``{w: 1}`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The use of read concern :readconcern:`"majority"` and write concern +:writeconcern:`{ w: 1 } <\>` in a causally consistent session +provides the following causal consistency guarantees *if causal consistency implies durability*: + +|xmark| Read own writes |checkmark| Monotonic reads |xmark| Monotonic writes |checkmark| Writes follow reads + +*If causal consistency does not imply durability*: + +|checkmark| Read own writes |checkmark| Monotonic reads |checkmark| Monotonic writes |checkmark| Writes follow reads + +.. topic:: Scenario 3 (Read Concern "majority" and Write Concern ``{w: 1}``) + + During the transient period with two primaries, because both ``P``\ + :sub:`old` and ``P``\ :sub:`new` can fulfill writes with + :writeconcern:`{ 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**: + + .. list-table:: + :header-rows: 1 + :class: no-outer-border + + * - Sequence + + - Example + + * - | 1. Write\ :sub:`1` with write concern :writeconcern:`{ w: 1 } <\>` to ``P``\ :sub:`old` + | 2. Read\ :sub:`1` with read concern :readconcern:`"majority"` to ``S``\ :sub:`2` + | 3. Write\ :sub:`2` with write concern :writeconcern:`{ w: 1 } <\>` to ``P``\ :sub:`new` + | 4. Read\ :sub:`2` with with read concern :readconcern:`"majority"` to ``S``\ :sub:`3` + + - | For item ``A``, update ``qty`` to ``50``. + | Read item ``A``. + | For items with ``qty`` less than ``50``, update ``reorder`` to ``true``. + | Read item ``A``. + + .. figure:: /images/causal-rc-majority-wc-1.svg + :alt: State of data with two primaries using read concern majority and write concern 1 + :figwidth: 450px + + In this sequence, + + - Read\ :sub:`1` cannot not return until the majority commit point has + advanced on ``P``\ :sub:`new` past the time of Write\ :sub:`1`. + + - Read\ :sub:`2` cannot not return until the majority commit point has + advanced on ``P``\ :sub:`new` past the time of Write\ :sub:`2`. + + - Write\ :sub:`1` will roll back when the network partition is healed. + + |arrow| *If causal consistency implies durability* + + .. list-table:: + :class: no-outer-border + :widths: 20 80 + + * - |xmark| **Read own writes** + + - Read\ :sub:`1` reads data from ``S``\ :sub:`2` that does not + reflect a state after Write\ :sub:`1`. + + * - |checkmark| **Monotonic reads** + + - Read\ :sub:`2` reads data from ``S``\ :sub:`3` that reflects + a state after Read\ :sub:`1` (i.e. an earlier state is + reflected in the data read by Read\ :sub:`1`). + + * - |xmark| **Monotonic writes** + + - Write\ :sub:`2` updates data on ``P``\ :sub:`new` that does + not reflect a state after Write\ :sub:`1`. + + * - |checkmark| **Writes follow reads** + + - Write\ :sub:`2` updates data on ``P``\ :sub:`new` that + reflects a state after Read\ :sub:`1` (i.e. an + earlier state reflects the data read by Read\ + :sub:`1`). + + |arrow| *If causal consistency does not imply durability* + + .. list-table:: + :class: no-outer-border + :widths: 20 80 + + * - |checkmark| **Read own writes** + + - Read\ :sub:`1` reads data from ``S``\ :sub:`2` returns data + that reflects a state equivalent to Write\ :sub:`1` followed + by rollback of Write\ :sub:`1`. + + * - |checkmark| **Monotonic reads** + + - Read\ :sub:`2` reads data from ``S``\ :sub:`3` that reflects + a state after Read\ :sub:`1` (i.e. an earlier state is + reflected in the data read by Read\ :sub:`1`). + + * - |checkmark| **Monotonic writes** + + - Write\ :sub:`2` updates data on ``P``\ :sub:`new` that is + equivalent to after Write\ :sub:`1` followed by rollback of Write\ + :sub:`1`. + + * - |checkmark| **Writes follow reads** + + - Write\ :sub:`2` updates data on ``P``\ :sub:`new` that + reflects a state after Read\ :sub:`1` (i.e. whose + earlier state reflects the data read by Read\ + :sub:`1`). + +.. topic:: Scenario 4 (Read Concern "majority" and Write Concern ``{w: 1}``) + + Consider an alternative sequence where Read\ :sub:`1` with + read concern :readconcern:`"majority"` routes to ``S``\ :sub:`1`: + + .. list-table:: :header-rows: 1 + :class: no-outer-border + + * - Sequence + + - Example + + * - | Write\ :sub:`1` with write concern :writeconcern:`{ w: 1 } <\>` to ``P``\ :sub:`old` + | Read\ :sub:`1` with read concern :readconcern:`"majority"` to ``S``\ :sub:`1` + | Write\ :sub:`2` with write concern :writeconcern:`{ w: 1 } <\>` to ``P``\ :sub:`new` + | Read\ :sub:`2` with with read concern :readconcern:`"majority"` to ``S``\ :sub:`3` + + - | For item ``A``, update ``qty`` to ``50``. + | Read item ``A``. + | For items with ``qty`` less than ``50``, update ``reorder`` to ``true``. + | Read item ``A``. + + In this sequence: + + - Read\ :sub:`1` cannot not return until the majority commit point + has advanced on ``S``\ :sub:`1`. This cannot occur until ``P``\ + :sub:`old` and ``S``\ :sub:`1` can communicate with the rest of + the replica set. At which time, ``P``\ :sub:`old` has stepped down + (if not already), Write\ :sub:`1` is rolled back from ``P``\ + :sub:`old` and ``S``\ :sub:`1`, and the two members sync from the + other members of the replica set. + + |arrow| *If causal consistency implies durability* + + .. list-table:: + :class: no-outer-border + :widths: 20 80 + + * - |xmark| **Read own writes** + + - The data read by Read\ :sub:`1` does not reflect the results + of Write\ :sub:`1`, which has rolled back. + + * - |checkmark| **Monotonic reads** + + - Read\ :sub:`2` reads data from ``S``\ :sub:`3` that reflects + a state after Read\ :sub:`1` (i.e. whose + earlier state reflects the data read by Read\ + :sub:`1`). + + * - |xmark| **Monotonic writes** + + - Write\ :sub:`2` updates data on ``P``\ :sub:`new` that does + not reflect a state after Write\ :sub:`1`, which had preceded + Write\ :sub:`2` but has rolled back. + + * - |checkmark| **Writes follow reads** + + - Write\ :sub:`2` updates data on ``P``\ :sub:`new` that + reflects a state after Read\ :sub:`1` (i.e. whose + earlier state reflects the data read by Read\ :sub:`1`). + + |arrow| *If causal consistency does not imply durability* + + .. list-table:: + :class: no-outer-border + :widths: 20 80 + + * - |checkmark| **Read own writes** + + - Read\ :sub:`1` returns data that reflects the final result of + Write\ :sub:`1` since Write\ :sub:`1` ultimately rolls back. + + * - |checkmark| **Monotonic reads** + + - Read\ :sub:`2` reads data from ``S``\ :sub:`3` that reflects + a state after Read\ :sub:`1` (i.e. an earlier state + reflects the data read by Read\ :sub:`1`). + + * - |checkmark| **Monotonic writes** + + - Write\ :sub:`2` updates data on ``P``\ :sub:`new` that is + equivalent to after Write\ :sub:`1` followed by rollback of Write\ + :sub:`1`. + + * - |checkmark| **Writes follow reads** + + - Write\ :sub:`2` updates data on ``P``\ :sub:`new` that + reflects a state after Read\ :sub:`1` (i.e. an earlier state + reflects the data read by Read\ :sub:`1`). + +.. _causal-rc-local-wc-1: + +Read Concern ``"local"`` and Write concern ``{w: 1}`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The use of read concern :readconcern:`"local"` and write concern +:writeconcern:`{ w: 1 } <\>` in a causally consistent session +cannot guarantee causal consistency. + +|xmark| Read own writes |xmark| Monotonic reads |xmark| Monotonic writes |xmark| Writes follow reads + +This combination may satisfy all four causal consistency guarantees in +some situations, but not necessarily in all situations. + +.. topic:: Scenario 5 (Read Concern "local" and Write Concern ``{w: 1}``) + + During this transient period, because both ``P``\ :sub:`old` and + ``P``\ :sub:`new` can fulfill writes with :writeconcern:`{ w: 1 } <\>` write concern, a + client session could issue the following sequence of operations + successfully but not be causally consistent: + + .. list-table:: :header-rows: 1 + :class: no-outer-border + + * - Sequence + + - Example + + * - | 1. Write\ :sub:`1` with write concern :writeconcern:`{ w: 1 } <\>` to ``P``\ :sub:`old` + | 2. Read\ :sub:`1` with read concern :readconcern:`"local"` to ``S``\ :sub:`1` + | 3. Write\ :sub:`2` with write concern :writeconcern:`{ w: 1 } <\>` to ``P``\ :sub:`new` + | 4. Read\ :sub:`2` with read concern :readconcern:`"local"` to ``S``\ :sub:`3` + + - | For item ``A``, update ``qty`` to ``50``. + | Read item ``A``. + | For items with ``qty`` less than ``50``, update ``reorder`` to ``true``. + | Read item ``A``. + + .. figure:: /images/causal-rc-local-wc-1.svg + :alt: State of data with two primaries using read concern local and write concern 1 + :figwidth: 450px + + .. list-table:: + :class: no-outer-border + :widths: 20 80 + + * - |xmark| Read own writes + + - Read\ :sub:`2` reads data from ``S``\ :sub:`3` that only + reflects a state after Write\ :sub:`2` and not Write\ :sub:`1` + followed by Write\ :sub:`2`. + + * - |xmark| Monotonic reads + + - Read\ :sub:`2` reads data from ``S``\ :sub:`3` that does not + reflect a state after Read\ :sub:`1` (i.e. an earlier state + does not reflect the data read by Read\ :sub:`1`). + + * - |xmark| Monotonic writes + + - Write\ :sub:`2` updates data on ``P``\ :sub:`new` that does + not reflect a state after Write\ :sub:`1`. + + * - |xmark| Write follow read + + - Write\ :sub:`2` updates data on ``P``\ :sub:`new` that does + not reflect a state after Read\ :sub:`1` (i.e. an earlier + state does not reflect the data read by Read\ :sub:`1`). + +.. _causal-rc-local-wc-majority: + +Read Concern ``"local"`` and Write concern ``"majority"`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The use of read concern :readconcern:`"local"` and write concern +:writeconcern:`"majority"` in a causally consistent session provides +the following causal consistency guarantees: + +|xmark| Read own writes |xmark| Monotonic reads |checkmark| Monotonic writes |xmark| Writes follow reads + +This combination may satisfy all four causal consistency guarantees in +some situations, but not necessarily in all situations. + +.. topic:: Scenario 6 (Read Concern "local" and Write Concern ``{w: 1}``) + + During this transient period, because only ``P``\ :sub:`new` can + fulfill writes with :writeconcern:`{ w: "majority" } <"majority">` write concern, a client + session could issue the following sequence of operations successfully + but not be causally consistent: + + .. list-table:: + :header-rows: 1 + + * - Sequence + + - Example + + * - | 1. Write\ :sub:`1` with write concern :writeconcern:`"majority"` to ``P``\ :sub:`new` + | 2. Read\ :sub:`1` with read concern :readconcern:`"local"` to ``S``\ :sub:`1` + | 3. Write\ :sub:`2` with write concern :writeconcern:`"majority"` to ``P``\ :sub:`new` + | 4. Read\ :sub:`2` with read concern :readconcern:`"local"` to ``S``\ :sub:`3` + + - | For item ``A``, update ``qty`` to ``50``. + | Read item ``A``. + | For items with ``qty`` less than ``50``, update ``reorder`` to ``true``. + | Read item ``A``. + + .. figure:: /images/causal-rc-local-wc-majority.svg + :alt: State of data with two primaries using read concern local and write concern majority + :figwidth: 550px + + .. list-table:: + :class: no-outer-border + :widths: 20 80 + + * - |xmark| Read own writes. + + - Read\ :sub:`1` reads data from ``S``\ :sub:`1` that does not + reflect a state after Write1\ :sub:`1`. + + * - |xmark| Monotonic reads. + + - Read\ :sub:`2` reads data from ``S``\ :sub:`3` that does not + reflect a state after Read\ :sub:`1` (i.e. an earlier state + does not reflect the data read by Read\ :sub:`1`). + + * - |checkmark| Monotonic writes + + - Write\ :sub:`2` updates data on ``P``\ :sub:`new` that + reflects a state after Write\ :sub:`1`. + + * - |xmark| Write follow read. + + - Write\ :sub:`2` updates data on ``P``\ :sub:`new` that does + not reflect a state after Read\ :sub:`1` (i.e. an earlier + state does not reflect the data read by Read\ :sub:`1`). + + +.. |arrow| unicode:: U+27A4 + +.. |checkmark| unicode:: U+2705 + +.. |xmark| unicode:: U+274C diff --git a/source/core/read-isolation-consistency-recency.txt b/source/core/read-isolation-consistency-recency.txt index 2b501596429..a87ead4c5b7 100644 --- a/source/core/read-isolation-consistency-recency.txt +++ b/source/core/read-isolation-consistency-recency.txt @@ -85,67 +85,94 @@ operation that deletes all documents based on a specified condition and a subsequent read operation that verifies the delete operation have a causal relationship. -With causal consistency, MongoDB executes causal operations in an order -that respect their causal relationships, and clients observe results -that are consistent with the causal relationships. +With causally consistent sessions, MongoDB executes causal operations +in an order that respect their causal relationships, and clients +observe results that are consistent with the causal relationships. .. _sessions: -Client Sessions -~~~~~~~~~~~~~~~ - -.. important:: +Client Sessions and Causal Consistency Guarantees +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - To use client sessions: +To provide causal consistency, MongoDB 3.6 enables causal consistency +in client sessions. A causally consistent session denotes that the +associated sequence of read operations with :readconcern:`"majority"` +read concern and write operations with :writeconcern:`"majority"` write +concern have a causal relationship that is reflected by their ordering. +Applications must ensure that only one thread at a time executes these +operations in a client session. - - Clients require MongoDB drivers updated for MongoDB 3.6: +For causally related operations: - .. include:: /includes/3.6-drivers.rst +#. A client starts a client session. - - ``featureCompatibilityVersion`` must be set to "3.6". For more - information, see :ref:`view-fcv` and - :dbcommand:`setFeatureCompatibilityVersion`. + .. important:: - The following discussion refers to client sessions, which are - separate from server sessions. + Client sessions only guarantee causal consistency for: -To provide causal consistency, MongoDB 3.6 enables causal consistency -in client sessions. A causally consistent session denotes that the -associated sequence of read and *acknowledged* write operations have a -causal relationship that is reflected by their ordering. Applications -must ensure that only one thread at a time executes these operations in -a client session. + - Read operations with :readconcern:`"majority"`; i.e. the return + data has been acknowledged by a majority of the replica set + members and is durable. -For causally related operations: + - Write operations with :writeconcern:`"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. -#. A client starts a client session. + For more information on causal consistency and various read and + write concerns, see + :doc:`/core/causal-consistency-read-write-concerns`. -#. As the client issues a sequence of read and write operations, the - client includes the session information with each operation. The - client uses a read concern to specify that each operation is - causally related to the previous one in the session. +#. As the client issues a sequence of read with + :readconcern:`"majority"` read concern and write operations (with + :writeconcern:`"majority"` write concern), the client includes the + session information with each operation. -#. For each read and *acknowledged* write operation associated with the - session, MongoDB returns the operation time and the cluster time, - even if the operation errors. The client session keeps track of the - operation time and the cluster time. +#. For each read operation with :readconcern:`"majority"` read concern + and write operation with :writeconcern:`"majority"` write concern + associated with the session, MongoDB returns the operation time and + the cluster time, even if the operation errors. The client session + keeps track of the operation time and the cluster time. .. note:: MongoDB does not return the operation time and the cluster time - for *unacknowledged* write operations. Unacknowledged writes do - not imply any causal relationship. + for *unacknowledged* (``w: 0``) write operations. Unacknowledged + writes do not imply any causal relationship. + + Although, MongoDB returns the operation time and the cluster time + for read operations and acknowledged write operations in a client + session, only the read operations with + :readconcern:`"majority"` read concern and write operations with + :writeconcern:`"majority"` write concern can guarantee causal + consistency. For details, see + :doc:`/core/causal-consistency-read-write-concerns`. #. The associated client session tracks these two time fields. + .. note:: + + Operations can be causally consistent across different sessions. + MongoDB drivers and the :binary:`~bin.mongo` shell provide the + methods to advance the operation time and the cluster time for a + client session. So, a client can advance the cluster time and the + operation time of one client session to be consistent with the + operations of another client session. + +.. _causal-consistency-guarantees: + +Causal Consistency Guarantees +````````````````````````````` + The following table lists the causal consistency guarantees provided by -causally consistent sessions for read and *acknowledged* write -operations. These guarantees hold across all members of the MongoDB -deployment. +causally consistent sessions for read operations with +:readconcern:`"majority"` read concern and +write operations with :writeconcern:`"majority"` write concern. .. list-table:: :header-rows: 1 - :widths: 30 70 + :widths: 22 78 + * - Guarantees - Description @@ -168,37 +195,130 @@ deployment. - read\ :sub:`1` returns results that reflect write\ :sub:`2` - then, read\ :sub:`2` cannot return results of write\ :sub:`1`. + then read\ :sub:`2` cannot return results of write\ :sub:`1`. * - Monotonic writes - Write operations that must precede other writes are executed before those other writes. + For example, if write\ :sub:`1` must precedes write\ :sub:`2` in + a session, the state of the data at the time of write\ :sub:`2` + must reflect the state of the data post write\ :sub:`1`. Other + writes can interleave between write\ :sub:`1` and write write\ + :sub:`2`, but write\ :sub:`2` cannot occur before write\ + :sub:`1`. + * - Writes follow reads - Write operations that must occur after read operations are - executed after those read operations. + 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. -These guarantees hold across all members of the MongoDB deployment. - For example, if, for a client session, you issue an acknowledged write - followed by a read from a secondary, the read operation will reflect - the state of the database after the write operation. +Read Preference +``````````````` - .. note:: +These guarantees hold across all members of the MongoDB deployment. For +example, if, in a causally consistent session, you issue a write with +:writeconcern:`"majority"` write concern followed by a read that reads +from a secondary (i.e. read preference :readmode:``) with +:readconcern:`"majority"` read concern, the read operation will reflect +the state of the database after the write operation. + +Isolation +````````` + +Operations within a causally consistent session are not isolated from +operations outside the session. If a concurrent write operation +interleaves between the session's write and read operations, the +session's read operation may return results that reflect a write +operation that occurred *after* the session's write operation. + +Feature Compatibility Version +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Operations within a client session are not isolated from - operations outside the session. If a concurrent write operation - interleaves between the session's write and read operations, the - session's read operation may return results that reflect a write - operation that occurred *after* the session's write operation. +The ``featureCompatibilityVersion`` (fCV) must be set to "3.6" or +greater. To check the fCV, run the following command: -Operations can be causally consistent across different sessions. - MongoDB drivers and the :binary:`~bin.mongo` shell provide the methods - to advance the operation time and advance the cluster time for a - client session. So, a client can advance the cluster time and the - operation time of one client session to be consistent with the operations - of another client session. +.. code-block:: javascript + + db.adminCommand( { getParameter: 1, featureCompatibilityVersion: 1 } ) + +For more information, see :ref:`view-fcv` and +:dbcommand:`setFeatureCompatibilityVersion`. + +MongoDB Drivers +~~~~~~~~~~~~~~~ + +Clients require MongoDB drivers updated for MongoDB 3.6 or later: + +.. include:: /includes/3.6-drivers.rst + +Examples +~~~~~~~~ + +.. important:: + + Causally consistent + sessions can only guarantee causal consistency for reads with + :readconcern:`"majority"` read concern and writes with + :writeconcern:`"majority"` write concern. + +Consider a collection ``items`` that maintains the current and +historical data for various items. Only the historical data has a +non-null ``end`` date. If the ``sku`` value for an item changes, the +document with the old ``sku`` value needs to be updated with the +``end`` date, after which the new document is inserted with the current +``sku`` value. The client can use a causally consistent session to +ensure that the update occurs before the insert. + +.. tabs-pillstrip:: languages + +.. tabs-drivers:: + + tabs: + - id: python + content: | + + .. literalinclude:: /driver-examples/test_examples.py + :language: python + :dedent: 8 + :start-after: Start Causal Consistency Example 1 + :end-before: End Causal Consistency Example 1 + - id: php + content: | + + .. literalinclude:: /driver-examples/DocumentationExamplesTest.php + :language: php + :dedent: 8 + :start-after: Start Causal Consistency Example 1 + :end-before: End Causal Consistency Example 1 + +If another client needs to read all current ``sku`` values, you can +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: + +.. tabs-drivers:: + + tabs: + - id: python + content: | + + .. literalinclude:: /driver-examples/test_examples.py + :language: python + :dedent: 8 + :start-after: Start Causal Consistency Example 2 + :end-before: End Causal Consistency Example 2 + - id: php + content: | + + .. literalinclude:: /driver-examples/DocumentationExamplesTest.php + :language: php + :dedent: 8 + :start-after: Start Causal Consistency Example 2 + :end-before: End Causal Consistency Example 2 .. _causal-consistency-limitations: @@ -254,3 +374,9 @@ causally consistent: background index builds - + +.. toctree:: + :hidden: + :titlesonly: + + /core/causal-consistency-read-write-concerns diff --git a/source/images/causal-rc-local-wc-1.svg b/source/images/causal-rc-local-wc-1.svg new file mode 100644 index 00000000000..e36604ddfa8 --- /dev/null +++ b/source/images/causal-rc-local-wc-1.svg @@ -0,0 +1,95 @@ + + + + + + + + + P + + + old + + + + + + + + S + + + 1 + + + + + {id: 5, item: "A", qty:200} + + + + + + + + P + + + new + + + + + + + S + + + 3 + + + + + + + S + + + 2 + + + + + + {id: 5, item: "A", qty:50} + + + + + + + + {id: 5, item: "A", qty:200} + + + + + + + W1 + + + R1 + + + W2 + + + {id: 5, item: "A", qty:200} + + + R2 + + + diff --git a/source/images/causal-rc-local-wc-majority.svg b/source/images/causal-rc-local-wc-majority.svg new file mode 100644 index 00000000000..9b5266e8a18 --- /dev/null +++ b/source/images/causal-rc-local-wc-majority.svg @@ -0,0 +1,95 @@ + + + + + + + + + P + + + old + + + + + + + + S + + + 1 + + + + + {id: 5, item: "A", qty:200} + + + + + + + + P + + + new + + + + + + + S + + + 3 + + + + + + + S + + + 2 + + + + + + {id: 5, item: "A", qty:50} + + + + + W1 + + + R1 + + + {id: 5, item: "A", qty:200} + + + + + + + W2 + + + R2 + + + + + + {id: 5, item: "A", qty:50, restock: true} + + + diff --git a/source/images/causal-rc-majority-wc-1.svg b/source/images/causal-rc-majority-wc-1.svg new file mode 100644 index 00000000000..4c694169eb5 --- /dev/null +++ b/source/images/causal-rc-majority-wc-1.svg @@ -0,0 +1,93 @@ + + + + + + + + + P + + + old + + + + + + + + S + + + 1 + + + + + {id: 5, item: "A", qty:200} + + + + + + + + P + + + new + + + + + + + S + + + 3 + + + + + + + S + + + 2 + + + + + + {id: 5, item: "A", qty:50} + + + + + + {id: 5, item: "A", qty:200} + + + + + + + W1 + + + R1 + + + W2 + + + {id: 5, item: "A", qty:200} + + + R2 + + + diff --git a/source/images/causal-rc-majority-wc-majority.svg b/source/images/causal-rc-majority-wc-majority.svg new file mode 100644 index 00000000000..e97b863d5e4 --- /dev/null +++ b/source/images/causal-rc-majority-wc-majority.svg @@ -0,0 +1,94 @@ + + + + + + + + + P + + + old + + + + + + + + S + + + 1 + + + + + {id: 5, item: "A", qty:200} + + + + + + + + P + + + new + + + + + + + S + + + 3 + + + + + + + S + + + 2 + + + + + + {id: 5, item: "A", qty:50} + + + + W1 + + + {id: 5, item: "A", qty:200} + + + + + + + W2 + + + R2 + + + + + + {id: 5, item: "A", qty:50, restock: true} + + + R1 + + + diff --git a/source/images/network-partition-two-primaries.svg b/source/images/network-partition-two-primaries.svg new file mode 100644 index 00000000000..d7be8bc9192 --- /dev/null +++ b/source/images/network-partition-two-primaries.svg @@ -0,0 +1,61 @@ + + + + + + + Network Partition + + + + + P + + + old + + + + + + + S + + + 1 + + + + + + + + P + + + new + + + + + + + S + + + 3 + + + + + + + S + + + 2 + + + + + diff --git a/source/includes/3.6-drivers.rst b/source/includes/3.6-drivers.rst index 345e76ad7c4..e9a15b2353f 100644 --- a/source/includes/3.6-drivers.rst +++ b/source/includes/3.6-drivers.rst @@ -1,7 +1,21 @@ -- Java 3.6 -- Python 3.6 -- C 1.9 -- Node 3.0 -- C# 2.5 -- Ruby 2.5 -- PHP 1.4 +.. list-table:: + :class: index-table + + * - Java 3.6+ + + Python 3.6+ + + C 1.9+ + + - C# 2.5+ + + Node 3.0+ + + Ruby 2.5+ + + - Perl 2.0+ + + PHPC 1.4+ + + Scala 2.2+ + diff --git a/source/reference/read-concern.txt b/source/reference/read-concern.txt index 374fbe6c687..6eeedb232eb 100644 --- a/source/reference/read-concern.txt +++ b/source/reference/read-concern.txt @@ -155,10 +155,12 @@ option: .. note:: - For operations in :ref:`causally consistent sessions - `, only :readconcern:`"local"` and - :readconcern:`"majority"` levels are available. - + For operations in a :ref:`causally consistent session + `, :readconcern:`"local"` and + :readconcern:`"majority"` levels are available. However, to guarantee + causal consistency, you must use :readconcern:`"majority"`. For + details, see :ref:`causal-consistency`. + The following operations support the ``readConcern`` option: - :dbcommand:`find` command diff --git a/source/reference/read-preference.txt b/source/reference/read-preference.txt index b1a9b7b8cc5..74ccf5713a1 100644 --- a/source/reference/read-preference.txt +++ b/source/reference/read-preference.txt @@ -26,6 +26,13 @@ Read Preference Reference For more information on read isolation level in MongoDB, see :doc:`/core/read-isolation-consistency-recency`. + Read preference also does not affect :ref:`causal consistency + `. The :ref:`causal consistency guarantees + ` provided by causally consistent sessions for read + operations with :readconcern:`"majority"` read concern and write + operations with :writeconcern:`"majority"` write concern hold across + all members of the MongoDB deployment. + .. index:: read preference; semantics .. _replica-set-read-preference-semantics: .. index:: read preference; modes @@ -175,24 +182,24 @@ temporarily have two primaries; however, only one primary will be capable of confirming writes with the :writeconcern:`"majority"` write concern. -- A partial :term:`network partition` may segregate a primary (``p``\ +- A partial :term:`network partition` may segregate a primary (``P``\ :sub:`old`) into a partition with a minority of the nodes, while the other side of the partition contains a majority of nodes. The partition with the majority will elect a new primary (``P``\ - :sub:`new`), but for a brief period, the old primary (``p``\ + :sub:`new`), but for a brief period, the old primary (``P``\ :sub:`old`) may still continue to serve reads and writes, as it has not yet detected that it can only see a minority of nodes in the - replica set. During this period, if the old primary (``p``\ + replica set. During this period, if the old primary (``P``\ :sub:`old`) is still visible to clients as a primary, reads from this primary may reflect stale data. -- A primary (``p``\ :sub:`old`) may become unresponsive, which will +- A primary (``P``\ :sub:`old`) may become unresponsive, which will trigger an election and a new primary (``P``\ :sub:`new`) can be elected, serving reads and writes. If the unresponsive primary - (``p``\ :sub:`old`) starts responding again, two primaries will be - visible for a brief period. The brief period will end when ``p``\ + (``P``\ :sub:`old`) starts responding again, two primaries will be + visible for a brief period. The brief period will end when ``P``\ :sub:`old` steps down. However, during the brief period, clients - might read from the old primary ``p``\ :sub:`old`, which can provide + might read from the old primary ``P``\ :sub:`old`, which can provide stale data. To increase consistency, you can disable automatic :term:`failover`;