Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

opt: add enable_durable_locking_for_serializable session variable #107749

Merged
merged 1 commit into from
Jul 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions pkg/sql/exec_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -3616,6 +3616,10 @@ func (m *sessionDataMutator) SetImplicitFKLockingForSerializable(val bool) {
m.data.ImplicitFKLockingForSerializable = val
}

func (m *sessionDataMutator) SetDurableLockingForSerializable(val bool) {
m.data.DurableLockingForSerializable = val
}

// Utility functions related to scrubbing sensitive information on SQL Stats.

// quantizeCounts ensures that the Count field in the
Expand Down
1 change: 1 addition & 0 deletions pkg/sql/logictest/testdata/logic_test/information_schema
Original file line number Diff line number Diff line change
Expand Up @@ -5288,6 +5288,7 @@ disallow_full_table_scans off
enable_auto_rehoming off
enable_create_stats_using_extremes off
enable_drop_enum_value on
enable_durable_locking_for_serializable off
enable_experimental_alter_column_type_general off
enable_implicit_fk_locking_for_serializable off
enable_implicit_select_for_update on
Expand Down
3 changes: 3 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/pg_catalog
Original file line number Diff line number Diff line change
Expand Up @@ -2726,6 +2726,7 @@ disallow_full_table_scans off N
distsql off NULL NULL NULL string
enable_auto_rehoming off NULL NULL NULL string
enable_create_stats_using_extremes off NULL NULL NULL string
enable_durable_locking_for_serializable off NULL NULL NULL string
enable_experimental_alter_column_type_general off NULL NULL NULL string
enable_implicit_fk_locking_for_serializable off NULL NULL NULL string
enable_implicit_select_for_update on NULL NULL NULL string
Expand Down Expand Up @@ -2887,6 +2888,7 @@ disallow_full_table_scans off N
distsql off NULL user NULL off off
enable_auto_rehoming off NULL user NULL off off
enable_create_stats_using_extremes off NULL user NULL off off
enable_durable_locking_for_serializable off NULL user NULL off off
enable_experimental_alter_column_type_general off NULL user NULL off off
enable_implicit_fk_locking_for_serializable off NULL user NULL off off
enable_implicit_select_for_update on NULL user NULL on on
Expand Down Expand Up @@ -3045,6 +3047,7 @@ distsql NULL NULL NULL
distsql_workmem NULL NULL NULL NULL NULL
enable_auto_rehoming NULL NULL NULL NULL NULL
enable_create_stats_using_extremes NULL NULL NULL NULL NULL
enable_durable_locking_for_serializable NULL NULL NULL NULL NULL
enable_experimental_alter_column_type_general NULL NULL NULL NULL NULL
enable_implicit_fk_locking_for_serializable NULL NULL NULL NULL NULL
enable_implicit_select_for_update NULL NULL NULL NULL NULL
Expand Down
1 change: 1 addition & 0 deletions pkg/sql/logictest/testdata/logic_test/show_source
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ disallow_full_table_scans off
distsql off
enable_auto_rehoming off
enable_create_stats_using_extremes off
enable_durable_locking_for_serializable off
enable_experimental_alter_column_type_general off
enable_implicit_fk_locking_for_serializable off
enable_implicit_select_for_update on
Expand Down
47 changes: 47 additions & 0 deletions pkg/sql/opt/exec/execbuilder/testdata/fk
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,29 @@ vectorized: true
estimated row count: 2
label: buffer 1

# Try again with durable locking enabled.
statement ok
SET enable_durable_locking_for_serializable = true

# TODO(michae2, 100194): Change this from EXPLAIN (OPT) to EXPLAIN.
query T
EXPLAIN (OPT) INSERT INTO child VALUES (1,1), (2,2)
----
insert child
├── values
│ ├── (1, 1)
│ └── (2, 2)
└── f-k-checks
└── f-k-checks-item: child(p) -> parent(p)
└── anti-join (lookup parent)
├── lookup columns are key
├── locking: for-share,durability-guaranteed
├── with-scan &1
└── filters (true)

statement ok
RESET enable_durable_locking_for_serializable

statement ok
RESET enable_implicit_fk_locking_for_serializable

Expand Down Expand Up @@ -644,6 +667,30 @@ vectorized: true
spans: FULL SCAN
locking strength: for share

# Try again with durable locking enabled.
statement ok
SET enable_durable_locking_for_serializable = true

# TODO(michae2, 100194): Change this from EXPLAIN (OPT) to EXPLAIN.
query T
EXPLAIN (OPT) UPDATE child SET p = 4
----
update child
├── project
│ ├── scan child
│ └── projections
│ └── 4
└── f-k-checks
└── f-k-checks-item: child(p) -> parent(p)
└── anti-join (merge)
├── with-scan &1
├── scan parent
│ └── locking: for-share,durability-guaranteed
└── filters (true)

statement ok
RESET enable_durable_locking_for_serializable

statement ok
RESET enable_implicit_fk_locking_for_serializable

Expand Down
81 changes: 81 additions & 0 deletions pkg/sql/opt/exec/execbuilder/testdata/select_for_update
Original file line number Diff line number Diff line change
Expand Up @@ -2560,3 +2560,84 @@ vectorized: true
spans: /2-/3
locking strength: for update
locking wait policy: skip locked

# ------------------------------------------------------------------------------
# Tests with durable locking.
# ------------------------------------------------------------------------------

statement ok
SET enable_durable_locking_for_serializable = true

# TODO(michae2, 100194): Change these from EXPLAIN (OPT) to EXPLAIN (VERBOSE).

query T
EXPLAIN (OPT) SELECT * FROM t FOR UPDATE
----
scan t
└── locking: for-update,durability-guaranteed

query T
EXPLAIN (OPT) SELECT * FROM t FOR NO KEY UPDATE
----
scan t
└── locking: for-no-key-update,durability-guaranteed

query T
EXPLAIN (OPT) SELECT * FROM t FOR SHARE
----
scan t
└── locking: for-share,durability-guaranteed

query T
EXPLAIN (OPT) SELECT * FROM t FOR KEY SHARE
----
scan t
└── locking: for-key-share,durability-guaranteed

query T
EXPLAIN (OPT) SELECT * FROM t FOR KEY SHARE FOR SHARE
----
scan t
└── locking: for-share,durability-guaranteed

query T
EXPLAIN (OPT) SELECT * FROM t FOR KEY SHARE FOR SHARE FOR NO KEY UPDATE
----
scan t
└── locking: for-no-key-update,durability-guaranteed

query T
EXPLAIN (OPT) SELECT * FROM t FOR KEY SHARE FOR SHARE FOR NO KEY UPDATE FOR UPDATE
----
scan t
└── locking: for-update,durability-guaranteed

query T
EXPLAIN (OPT) SELECT * FROM t FOR UPDATE OF t
----
scan t
└── locking: for-update,durability-guaranteed

query T
EXPLAIN (OPT) SELECT (SELECT a FROM t FOR UPDATE OF t)
----
values
└── tuple
└── subquery
└── max1-row
└── scan t
└── locking: for-update,durability-guaranteed

query T
EXPLAIN (OPT) SELECT * FROM t WHERE a IN (SELECT b FROM t FOR UPDATE)
----
project
└── inner-join (lookup t)
├── lookup columns are key
├── distinct-on
│ └── scan t
│ └── locking: for-update,durability-guaranteed
└── filters (true)

statement ok
RESET enable_durable_locking_for_serializable
3 changes: 3 additions & 0 deletions pkg/sql/opt/memo/memo.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ type Memo struct {
useImprovedComputedColumnFiltersDerivation bool
useImprovedJoinElimination bool
implicitFKLockingForSerializable bool
durableLockingForSerializable bool

// txnIsoLevel is the isolation level under which the plan was created. This
// affects the planning of some locking operations, so it must be included in
Expand Down Expand Up @@ -238,6 +239,7 @@ func (m *Memo) Init(ctx context.Context, evalCtx *eval.Context) {
useImprovedComputedColumnFiltersDerivation: evalCtx.SessionData().OptimizerUseImprovedComputedColumnFiltersDerivation,
useImprovedJoinElimination: evalCtx.SessionData().OptimizerUseImprovedJoinElimination,
implicitFKLockingForSerializable: evalCtx.SessionData().ImplicitFKLockingForSerializable,
durableLockingForSerializable: evalCtx.SessionData().DurableLockingForSerializable,
txnIsoLevel: evalCtx.TxnIsoLevel,
}
m.metadata.Init()
Expand Down Expand Up @@ -386,6 +388,7 @@ func (m *Memo) IsStale(
m.useImprovedComputedColumnFiltersDerivation != evalCtx.SessionData().OptimizerUseImprovedComputedColumnFiltersDerivation ||
m.useImprovedJoinElimination != evalCtx.SessionData().OptimizerUseImprovedJoinElimination ||
m.implicitFKLockingForSerializable != evalCtx.SessionData().ImplicitFKLockingForSerializable ||
m.durableLockingForSerializable != evalCtx.SessionData().DurableLockingForSerializable ||
m.txnIsoLevel != evalCtx.TxnIsoLevel {
return true, nil
}
Expand Down
6 changes: 6 additions & 0 deletions pkg/sql/opt/memo/memo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,12 @@ func TestMemoIsStale(t *testing.T) {
evalCtx.SessionData().ImplicitFKLockingForSerializable = false
notStale()

// Stale enable_durable_locking_for_serializable.
evalCtx.SessionData().DurableLockingForSerializable = true
stale()
evalCtx.SessionData().DurableLockingForSerializable = false
notStale()

// Stale txn isolation level.
evalCtx.TxnIsoLevel = isolation.ReadCommitted
stale()
Expand Down
16 changes: 11 additions & 5 deletions pkg/sql/opt/optbuilder/select.go
Original file line number Diff line number Diff line change
Expand Up @@ -697,16 +697,22 @@ func (b *Builder) buildScan(
}
if locking.isSet() {
private.Locking = locking.get()
if b.evalCtx.TxnIsoLevel != isolation.Serializable {
if b.evalCtx.TxnIsoLevel != isolation.Serializable ||
b.evalCtx.SessionData().DurableLockingForSerializable {
// Under weaker isolation levels we use fully-durable locks for SELECT FOR
// UPDATE statements, SELECT FOR SHARE statements, and all other locked
// scans (e.g. FK checks), regardless of locking strength and wait
// policy. Unlike mutation statements, SELECT FOR UPDATE statements do not
// lay down intents, so we cannot rely on the durability of intents to
// UPDATE statements, SELECT FOR SHARE statements, and constraint checks
// (e.g. FK checks), regardless of locking strength and wait policy.
// Unlike mutation statements, SELECT FOR UPDATE statements do not lay
// down intents, so we cannot rely on the durability of intents to
// guarantee exclusion until commit as we do for mutation statements. And
// unlike serializable isolation, weaker isolation levels do not perform
// read refreshing, so we cannot rely on read refreshing to guarantee
// exclusion.
//
// Under serializable isolation we only use fully-durable locks if
// enable_durable_locking_for_serializable is set. (Serializable isolation
// does not require locking for correctness, so by default we use
// best-effort locks for better performance.)
private.Locking.Durability = tree.LockDurabilityGuaranteed
}
if private.Locking.WaitPolicy == tree.LockWaitSkipLocked && tab.FamilyCount() > 1 {
Expand Down
6 changes: 6 additions & 0 deletions pkg/sql/sessiondatapb/local_only_session_data.proto
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,12 @@ message LocalOnlySessionData {
bool implicit_fk_locking_for_serializable = 108 [
(gogoproto.customname) = "ImplicitFKLockingForSerializable"
];
// DurableLockingForSerializable is true if we should use durable locking for
// SELECT FOR UPDATE statements, SELECT FOR SHARE statements, and constraint
// checks under serializable isolation. (Serializable isolation does not
// require locking for correctness, so by default we use best-effor locks for
// better performance.) Weaker isolation levels always use durable locking.
bool durable_locking_for_serializable = 109;

///////////////////////////////////////////////////////////////////////////
// WARNING: consider whether a session parameter you're adding needs to //
Expand Down
17 changes: 17 additions & 0 deletions pkg/sql/vars.go
Original file line number Diff line number Diff line change
Expand Up @@ -2834,6 +2834,23 @@ var varGen = map[string]sessionVar{
},
GlobalDefault: globalFalse,
},

// CockroachDB extension.
`enable_durable_locking_for_serializable`: {
GetStringVal: makePostgresBoolGetStringValFn(`enable_durable_locking_for_serializable`),
Set: func(_ context.Context, m sessionDataMutator, s string) error {
b, err := paramparse.ParseBoolVar("enable_durable_locking_for_serializable", s)
if err != nil {
return err
}
m.SetDurableLockingForSerializable(b)
return nil
},
Get: func(evalCtx *extendedEvalContext, _ *kv.Txn) (string, error) {
return formatBoolAsPostgresSetting(evalCtx.SessionData().DurableLockingForSerializable), nil
},
GlobalDefault: globalFalse,
},
}

func ReplicationModeFromString(s string) (sessiondatapb.ReplicationMode, error) {
Expand Down