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 }