github.com/cockroachdb/cockroachdb-parser@v0.23.3-0.20240213214944-911057d40c9a/pkg/kv/kvserver/concurrency/isolation/levels.go (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 // Package isolation provides type definitions for isolation level-related 12 // concepts used by concurrency control in the key-value layer. 13 package isolation 14 15 import "github.com/gogo/protobuf/proto" 16 17 // WeakerThan returns true if the receiver's strength is weaker than the 18 // parameter's strength. It returns false if the two isolation levels are 19 // equivalent or if the parameter's strength is weaker than the receiver's. 20 // 21 // WARNING: Because isolation levels are defined from strongest to weakest in 22 // their enumeration (which is important for backwards compatability), their 23 // value comparison semantics do not represent a comparison of strength. The 24 // equality operators (==, !=) may be used to match a specific isolation level, 25 // but ordering operators (<, <=, >, >=) must not be used. Use this method 26 // instead. 27 func (l Level) WeakerThan(l2 Level) bool { 28 // Internally, we exploit the fact that the enum's value comparison semantics 29 // represent a comparison of the inverse of strength. Users of isolation level 30 // outside this package should not rely on this. 31 return l > l2 32 } 33 34 // ToleratesWriteSkew returns whether the isolation level permits write skew. In 35 // an MVCC system, this property can be expressed as whether the isolation level 36 // allows transactions to write and commit at an MVCC timestamp above the MVCC 37 // timestamp of its read snapshot(s). 38 func (l Level) ToleratesWriteSkew() bool { 39 return l.WeakerThan(Serializable) 40 } 41 42 // PerStatementReadSnapshot returns whether the isolation level establishes a 43 // new read snapshot for each statement. If not, a single read snapshot is used 44 // for the entire transaction. 45 func (l Level) PerStatementReadSnapshot() bool { 46 return l == ReadCommitted 47 } 48 49 var levelNameLower = map[int32]string{ 50 int32(Serializable): "serializable", 51 int32(Snapshot): "snapshot", 52 int32(ReadCommitted): "read committed", 53 } 54 55 func init() { 56 if len(levelNameLower) != len(Level_name) { 57 panic("missing lower-case name for isolation level") 58 } 59 } 60 61 // StringLower returns the lower-case name of the isolation level. 62 func (l Level) StringLower() string { 63 return proto.EnumName(levelNameLower, int32(l)) 64 } 65 66 // SafeValue implements the redact.SafeValue interface. 67 func (Level) SafeValue() {} 68 69 // Levels returns a list of all isolation levels, ordered from strongest to 70 // weakest. 71 func Levels() []Level { return []Level{Serializable, Snapshot, ReadCommitted} } 72 73 // RunEachLevel calls f in a subtest for each isolation level. 74 func RunEachLevel[T testingTB[T]](t T, f func(T, Level)) { 75 for _, l := range Levels() { 76 t.Run(l.String(), func(t T) { f(t, l) }) 77 } 78 } 79 80 // testingTB is an interface that matches *testing.T and *testing.B, without 81 // incurring the package dependency. 82 type testingTB[T any] interface { 83 Run(name string, f func(t T)) bool 84 }