github.com/cockroachdb/cockroachdb-parser@v0.23.3-0.20240213214944-911057d40c9a/pkg/kv/kvserver/concurrency/isolation/levels.proto (about)

     1  // Copyright 2023 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  syntax = "proto3";
    12  package cockroach.kv.kvserver.concurrency.isolation;
    13  option go_package = "github.com/cockroachdb/cockroach/pkg/kv/kvserver/concurrency/isolation";
    14  
    15  import "gogoproto/gogo.proto";
    16  
    17  // Level represents the different transaction isolation levels, which define how
    18  // concurrent transactions are allowed to interact and the isolation guarantees
    19  // that are made to individual transactions. Conceptually, isolation levels
    20  // achieve this by controlling how and when the changes made by one transaction
    21  // become visible to other transactions.
    22  //
    23  // Isolation levels in this enumeration are ordered from strongest to weakest.
    24  // Strong isolation levels provide a high degree of isolation between concurrent
    25  // transactions. They limit or eliminate the forms of concurrency effects that
    26  // transactions may observe. Weak isolation levels are more permissive. They
    27  // trade off isolation guarantees for improved performance. Transactions run
    28  // under weaker isolation levels block less and encounter fewer retry errors. In
    29  // some cases, they also perform less work.
    30  //
    31  // WARNING: Because isolation levels are defined from strongest to weakest in
    32  // this enumeration (which is important for backwards compatability), their
    33  // value comparison semantics do not represent a comparison of strength. The
    34  // equality operators (==, !=) may be used to match a specific isolation level,
    35  // but ordering operators (<, <=, >, >=) must not be used. Use the WeakerThan
    36  // method instead.
    37  //
    38  // Background
    39  //
    40  // Transaction isolation levels have historically been defined in multiple ways.
    41  //
    42  // ANSI SQL[^1] defined four isolation levels: READ UNCOMMITTED, READ COMMITTED,
    43  // REPEATABLE READ, and SERIALIZABLE. The levels were defined in terms of three
    44  // _phenomena_: Dirty Reads, Non-Repeatable Reads, and Phantom Reads. Stronger
    45  // isolation levels allow fewer phenomena to occur. As a result, they permit
    46  // less anomalous behavior ("permit fewer anomalies"). Weaker isolation levels
    47  // allow more phenomena to occur.
    48  //
    49  //  | Isolation Level  | Dirty Read   | Non-repeatable Read | Phantom Read |
    50  //  | ---------------- | ------------ | ------------------- | ------------ |
    51  //  | Read Uncommitted | Possible     | Possible            | Possible     |
    52  //  | Read Committed   | Not Possible | Possible            | Possible     |
    53  //  | Repeatable Read  | Not Possible | Not Possible        | Possible     |
    54  //  | Serializable     | Not Possible | Not Possible        | Not Possible |
    55  //
    56  // "A Critique of ANSI SQL Isolation Levels"[^2] demonstrated that the ANSI SQL
    57  // standard definitions of isolation levels were insufficient. Some phenomena
    58  // were ambiguous, while others were missing entirely. The work provided a new
    59  // characterization of isolation levels, defining the levels using a set of
    60  // eight different phenomena. The expanded characterization also made room for a
    61  // new isolation level: SNAPSHOT.
    62  //
    63  // While more complete, these definitions were still based on preventing
    64  // conflicting operations that could lead to anomalies from executing
    65  // concurrently. Adya’s dissertation "Weak Consistency: A Generalized Theory and
    66  // Optimistic Implementations for Distributed Transactions"[^3] argued that this
    67  // _preventative_ approach is overly restrictive. The definitions were
    68  // “disguised versions of locking” and therefore disallow optimistic and
    69  // multi-versioning schemes. Adya’s work generalizes existing isolation levels
    70  // in terms of conflicts, serialization graphs, and the forms of phenomena
    71  // allowed in the serialization graphs of different isolation levels.
    72  //
    73  // While these formalizations of isolation levels differ in their classification
    74  // approach (e.g. permitted anomalies vs. permitted histories), all three leave
    75  // room for a large degree of implementation freedom, leading to a diverse
    76  // landscape of database systems with unique approaches towards transaction
    77  // isolation that all "conform to the specification".
    78  //
    79  // Implementation
    80  //
    81  // CockroachDB implements three isolation levels: READ COMMITTED, SNAPSHOT, and
    82  // SERIALIZABLE, which loosely map on to each of the classifications presented
    83  // above. The system also exposes REPEATABLE READ, which maps to SNAPSHOT, and
    84  // READ UNCOMMITTED, which maps to READ COMMITTED.
    85  //
    86  // It contrasts the three isolation levels using a pair of properties:
    87  //
    88  // Write Skew Tolerance: Does the isolation level permit write skew? In an MVCC
    89  // system, this property can be expressed as whether the isolation level allows
    90  // transactions to write and commit at an MVCC timestamp above the MVCC
    91  // timestamp of its read snapshot(s).
    92  //
    93  // Read Snapshot Scope: Does the isolation level allow transactions to operate
    94  // across multiple read snapshots? If not, a single read snapshot is used for
    95  // the entire transaction. If so, what is the scope of each read snapshot?
    96  //
    97  // With these two properties in hand, CockroachDB then constructs a unifying
    98  // framework for its three supported isolation levels:
    99  //
   100  //  | Isolation Level     | Write Skew Tolerance | Read Snapshot Scope |
   101  //  |---------------------|----------------------|---------------------|
   102  //  | Serializable (SSI)  | No                   | Per-Transaction     |
   103  //  | Snapshot (SI)       | Yes                  | Per-Transaction     |
   104  //  | Read Committed (RC) | Yes                  | Per-Statement       |
   105  //
   106  // Write Skew Tolerance characterizes the difference between Snapshot and
   107  // Serializable isolation. Snapshot transactions permit write skew, so they
   108  // can commit at a later timestamp than their read timestamp. Serializable
   109  // transactions proscribe write skew, so they must commit at their read
   110  // timestamp. These transactions accomplish this by refreshing their reads to
   111  // their commit timestamp at commit time, effectively advancing their read
   112  // timestamp forward while verifying equivalence with their original read
   113  // timestamp. When a read refresh fails validation, the transaction must
   114  // restart. For more details, see the comment on txnSpanRefresher.
   115  //
   116  // Read Snapshot Scope characterizes the difference between Snapshot isolation
   117  // and Read Committed isolation. Snapshot transactions use a single consistent
   118  // read snapshot across their entire lifetime, ensuring "repeatable reads" and
   119  // avoiding "phantoms" across statements. When the transaction's read snapshot
   120  // must change due to contention (e.g. on a write-write conflict to avoid lost
   121  // updates, or on a read uncertainty error to enforce real-time ordering), the
   122  // transaction must restart. Conversely, Read Committed transactions use a new
   123  // read snapshot for each statement. The use of multiple read snapshots across
   124  // the lifetime of a transaction permits anomalies like non-repeatable reads
   125  // between statements. However, this scoping benefits from only requiring
   126  // statement-level retries when a read snapshot must change. As a result, these
   127  // retries can commonly be handled gateway-side without application involvement.
   128  //
   129  // For more about isolation levels in CockroachDB, see the Read Committed RFC:
   130  //  cockroachdb/cockroach/docs/RFCS/20230122_read_committed_isolation.md
   131  //
   132  // References
   133  //
   134  // [^1]: 1992, https://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt
   135  //
   136  // [^2]: 1995, https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/tr-95-51.pdf
   137  //
   138  // [^3]: 1999, https://pmg.csail.mit.edu/papers/adya-phd.pdf
   139  //
   140  enum Level {
   141    option (gogoproto.goproto_enum_prefix) = false;
   142  
   143    // Serializable provides the strictest transaction isolation. The isolation
   144    // level emulates serial transaction execution for all committed transactions;
   145    // as if transactions had been executed one after another, serially, rather
   146    // than concurrently.
   147    //
   148    // Serializable isolation is commonly implemented using two-phase locking
   149    // [2PL]. However, CockroachDB does not use two-phase locking. Instead, its
   150    // implementation of Serializable isolation uses an optimistic concurrency
   151    // control algorithm that is related to Serializable Snapshot Isolation [SSI]
   152    // and is probably most accurately described as a variant of Write-Snapshot
   153    // Isolation [WSI]. These two algorithms live in a family of concurrency
   154    // control schemes that extend the multi-versioning present in Snapshot
   155    // Isolation with additional runtime conflict detection to provide
   156    // Serializable Isolation.
   157    //
   158    // [2PL]: https://en.wikipedia.org/wiki/Two-phase_locking
   159    // [SSI]: https://dl.acm.org/doi/10.1145/1620585.1620587
   160    // [WSI]: https://dl.acm.org/doi/10.1145/2168836.2168853
   161    Serializable = 0;
   162  
   163    // Snapshot provides moderately strict transaction isolation. A transaction
   164    // using the isolation level sees only data committed before the transaction
   165    // began; it never sees either uncommitted data or changes committed during
   166    // transaction execution by concurrent transactions. A transaction using this
   167    // isolation level is also prevented from writing to data that has changed
   168    // since the transaction began ("first committer wins"), preventing lost
   169    // updates.
   170    //
   171    // Snapshot isolation is commonly built upon Multi-Version Concurrency Control
   172    // (MVCC), which allows to isolation level to provide efficient concurrent
   173    // access to reads and writes in different transactions that operate on the
   174    // same data.
   175    Snapshot = 1;
   176  
   177    // ReadCommitted provides relatively weak transaction isolation. Each
   178    // statement in a transaction using this isolation level sees only data
   179    // committed before that statement began. However, two successive statements
   180    // can see different data.
   181    //
   182    // For more about ReadCommitted, see the Read Committed RFC:
   183    //  cockroachdb/cockroach/docs/RFCS/20230122_read_committed_isolation.md
   184    ReadCommitted = 2;
   185  }