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

clarify isolation level upgrades #19490

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open

Conversation

taroface
Copy link
Contributor

@taroface taroface commented Apr 3, 2025

@taroface taroface requested review from rafiss and michae2 April 3, 2025 20:18
Copy link

netlify bot commented Apr 3, 2025

Deploy Preview for cockroachdb-api-docs canceled.

Name Link
🔨 Latest commit 92214a1
🔍 Latest deploy log https://app.netlify.com/sites/cockroachdb-api-docs/deploys/67f7bfcdae3e56000805765b

Copy link

netlify bot commented Apr 3, 2025

Deploy Preview for cockroachdb-interactivetutorials-docs canceled.

Name Link
🔨 Latest commit 92214a1
🔍 Latest deploy log https://app.netlify.com/sites/cockroachdb-interactivetutorials-docs/deploys/67f7bfcd5fe2b1000875cd81

Copy link

netlify bot commented Apr 3, 2025

Netlify Preview

Name Link
🔨 Latest commit 92214a1
🔍 Latest deploy log https://app.netlify.com/sites/cockroachdb-docs/deploys/67f7bfcdc2e1e0000827d70d
😎 Deploy Preview https://deploy-preview-19490--cockroachdb-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

Copy link

@michae2 michae2 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This LGTM! I have a couple of suggestions, but you can take or leave them as you see fit. Thanks for doing this!

Eventually we need to document sql.txn.snapshot_isolation.enabled but I'll leave it up to @dikshant on the timing of that (I don't think 25.2 is the time).


{% include_cached new-in.html version="v23.2" %} If [`READ COMMITTED` isolation is enabled]({% link {{ page.version.version }}/read-committed.md %}#enable-read-committed-isolation) using the `sql.txn.read_committed_isolation.enabled` [cluster setting]({% link {{ page.version.version }}/cluster-settings.md %}), `READ COMMITTED` is no longer an alias for `SERIALIZABLE`, and `READ UNCOMMITTED` becomes an alias for `READ COMMITTED`.
If `sql.txn.read_committed_isolation.enabled` is set to `false` (disabling `READ COMMITTED` isolation), all isolation levels upgrade to `SERIALIZABLE`.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: It might be clearer to make "transactions" the subject of the sentence rather than "isolation levels", something like:

If sql.txn.read_committed_isolation.enabled is set to false (disabling READ COMMITTED isolation), all transactions run under SERIALIZABLE isolation regardless of the isolation level requested.


#### Comparison
If a transaction includes [DDL]({% link {{ page.version.version }}/sql-statements.md %}#data-definition-statements) or [`AOST`]({% link {{ page.version.version }}/as-of-system-time.md %}) statements, all isolation levels upgrade to `SERIALIZABLE`.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I played around with this a bit, and I think we should not say anything about AOST. I believe the upgrade to serializable behavior for AOST transactions happens entirely in the KV layer. The SQL layer still considers AOST transactions to have read committed isolation, so it probably just confuses things to say they're upgraded.

@rafiss is this correct about DDL? Do we silently commit the transaction and start a new one for DDL?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with not mentioning AOST here.

As for DDL, yes that's correct, we will upgrade the transaction to SERIALIZABLE if possible -- meaning as long as the transaction hasn't performed any work yet, it will be upgraded. (https://github.com/cockroachdb/cockroach/blob/3acb6e287300ad4df232e2e4028af2f2435c5220/pkg/sql/conn_executor_ddl.go#L76)

Let's not mention autocommit behavior around DDLs here though. That's a separate piece of functionality, controlled by the autocommit_before_ddl setting.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks both for clarifying these points. I'm just going to avoid talking about AOST and DDL txns altogether, since we have this open issue that could update the behavior again at some point.

| `READ COMMITTED` | -- |
| `REPEATABLE READ` | `SNAPSHOT` |
| `SNAPSHOT` | `SERIALIZABLE` |
| `SERIALIZABLE` | -- |
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Sorry, this is bikeshedding, you can ignore this comment unless you feel convinced 🙂.)

This table isn't incorrect, but IMO the REPEATABLE READ -> SNAPSHOT -> SERIALIZABLE upgrade chain idea is a little confusing and puts more emphasis on "upgrades" than I think they're worth.

If I were writing this I think I would say first (or last) that READ UNCOMMITTED is an alias for READ COMMITTED and REPEATABLE READ is an alias for SNAPSHOT and then I wouldn't mention those levels again. And then I would only describe the upgrades in terms of READ COMMITTED, SNAPSHOT, and SERIALIZABLE, which are the three "real" isolation levels we support. I think that would put the emphasis in the right place.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this! The reason I thought to highlight READ UNCOMMITTED as an 'upgrade' to READ COMMITTED is because the Upgrades to SQL Isolation Level chart seems to track that exact 'upgrade,' which became part of a customer issue recently. That's why I've been confused about "alias" vs "upgrade". cc @rafiss

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, thanks for explaining. Now I understand.

From some experimentation, looks like:

  • READ UNCOMMITTED -> READ COMMITTED does increment the metric
  • REPEATABLE READ -> SNAPSHOT does not increment the metric
  • READ COMMITTED -> SERIALIZABLE does increment the metric
  • SNAPSHOT -> SERIALIZABLE does increment the metric

So I guess only REPEATABLE READ could be considered an alias for SNAPSHOT, and the rest are upgrades?

Here's how I figured that out:

[email protected]:26257/demoapp/defaultdb> \set show_times=false
[email protected]:26257/demoapp/defaultdb> SET CLUSTER SETTING sql.txn.repeatable_read_isolation.enabled = true;
SET CLUSTER SETTING
[email protected]:26257/demoapp/defaultdb> SELECT DISTINCT variable, value FROM [SHOW ALL CLUSTER SETTINGS] WHERE variable LIKE '%isolation%';
                  variable                  | value
--------------------------------------------+--------
  sql.txn.read_committed_isolation.enabled  | true
  sql.txn.repeatable_read_isolation.enabled | true
(2 rows)
[email protected]:26257/demoapp/defaultdb> SELECT * FROM crdb_internal.node_metrics WHERE name LIKE '%iso_level%' ORDER BY name;
  store_id |                   name                    | value
-----------+-------------------------------------------+--------
      NULL | sql.txn.upgraded_iso_level.count          |     0
      NULL | sql.txn.upgraded_iso_level.count.internal |     0
(2 rows)
[email protected]:26257/demoapp/defaultdb> BEGIN TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; EXPLAIN ANALYZE SELECT 1; COMMIT;
BEGIN
                   info
-------------------------------------------
  planning time: 332µs
  execution time: 357µs
  distribution: local
  vectorized: true
  plan type: custom
  maximum memory usage: 10 KiB
  DistSQL network usage: 0 B (0 messages)
  regions: us-east1
  sql cpu time: 50µs
  estimated RUs consumed: 0
  isolation level: read committed
  priority: normal
  quality of service: regular

  • values
    sql nodes: n1
    regions: us-east1
    actual row count: 1
    execution time: 49µs
    sql cpu time: 50µs
    size: 1 column, 1 row
(21 rows)
COMMIT
[email protected]:26257/demoapp/defaultdb> SELECT * FROM crdb_internal.node_metrics WHERE name LIKE '%iso_level%' ORDER BY name;
  store_id |                   name                    | value
-----------+-------------------------------------------+--------
      NULL | sql.txn.upgraded_iso_level.count          |     1
      NULL | sql.txn.upgraded_iso_level.count.internal |     0
(2 rows)
[email protected]:26257/demoapp/defaultdb> BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; EXPLAIN ANALYZE SELECT 1; COMMIT;
BEGIN
                   info
-------------------------------------------
  planning time: 263µs
  execution time: 272µs
  distribution: local
  vectorized: true
  plan type: generic, re-optimized
  maximum memory usage: 10 KiB
  DistSQL network usage: 0 B (0 messages)
  regions: us-east1
  sql cpu time: 46µs
  estimated RUs consumed: 0
  isolation level: snapshot
  priority: normal
  quality of service: regular

  • values
    sql nodes: n1
    regions: us-east1
    actual row count: 1
    execution time: 46µs
    sql cpu time: 46µs
    size: 1 column, 1 row
(21 rows)
COMMIT
[email protected]:26257/demoapp/defaultdb> SELECT * FROM crdb_internal.node_metrics WHERE name LIKE '%iso_level%' ORDER BY name;
  store_id |                   name                    | value
-----------+-------------------------------------------+--------
      NULL | sql.txn.upgraded_iso_level.count          |     1
      NULL | sql.txn.upgraded_iso_level.count.internal |     0
(2 rows)
[email protected]:26257/demoapp/defaultdb> SET CLUSTER SETTING sql.txn.repeatable_read_isolation.enabled = false;
SET CLUSTER SETTING
[email protected]:26257/demoapp/defaultdb> SET CLUSTER SETTING sql.txn.read_committed_isolation.enabled = false;
SET CLUSTER SETTING
[email protected]:26257/demoapp/defaultdb> SELECT DISTINCT variable, value FROM [SHOW ALL CLUSTER SETTINGS] WHERE variable LIKE '%isolation%';
                  variable                  | value
--------------------------------------------+--------
  sql.txn.read_committed_isolation.enabled  | false
  sql.txn.repeatable_read_isolation.enabled | false
(2 rows)
[email protected]:26257/demoapp/defaultdb> BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; EXPLAIN ANALYZE SELECT 1; COMMIT;
BEGIN
                   info
-------------------------------------------
  planning time: 349µs
  execution time: 362µs
  distribution: local
  vectorized: true
  plan type: generic, re-optimized
  maximum memory usage: 10 KiB
  DistSQL network usage: 0 B (0 messages)
  regions: us-east1
  sql cpu time: 67µs
  estimated RUs consumed: 0
  isolation level: serializable
  priority: normal
  quality of service: regular

  • values
    sql nodes: n1
    regions: us-east1
    actual row count: 1
    execution time: 67µs
    sql cpu time: 67µs
    size: 1 column, 1 row
(21 rows)
COMMIT
[email protected]:26257/demoapp/defaultdb> SELECT * FROM crdb_internal.node_metrics WHERE name LIKE '%iso_level%' ORDER BY name;
  store_id |                   name                    | value
-----------+-------------------------------------------+--------
      NULL | sql.txn.upgraded_iso_level.count          |     2
      NULL | sql.txn.upgraded_iso_level.count.internal |     0
(2 rows)
[email protected]:26257/demoapp/defaultdb> BEGIN TRANSACTION ISOLATION LEVEL SNAPSHOT; EXPLAIN ANALYZE SELECT 1; COMMIT;
BEGIN
                   info
-------------------------------------------
  planning time: 81µs
  execution time: 148µs
  distribution: local
  vectorized: true
  plan type: generic, reused
  maximum memory usage: 10 KiB
  DistSQL network usage: 0 B (0 messages)
  regions: us-east1
  sql cpu time: 24µs
  estimated RUs consumed: 0
  isolation level: serializable
  priority: normal
  quality of service: regular

  • values
    sql nodes: n1
    regions: us-east1
    actual row count: 1
    execution time: 24µs
    sql cpu time: 24µs
    size: 1 column, 1 row
(21 rows)
COMMIT
[email protected]:26257/demoapp/defaultdb> SELECT * FROM crdb_internal.node_metrics WHERE name LIKE '%iso_level%' ORDER BY name;
  store_id |                   name                    | value
-----------+-------------------------------------------+--------
      NULL | sql.txn.upgraded_iso_level.count          |     3
      NULL | sql.txn.upgraded_iso_level.count.internal |     0
(2 rows)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1, let's treat READ UNCOMMITTED -> READ COMMITTED as an upgrade of the isolation level, since they are clearly defined as different levels in PG docs and in the SQL standard.

And also +1 to treating SNAPSHOT and REPEATABLE READ as pure aliases of each other. However, the caveat with this is that this isolation level is not enabled by default. It's gated behind the cluster setting sql.txn.repeatable_read_isolation.enabled, which defaults to false (and this setting also has an alias sql.txn.snapshot_isolation.enabled). I'm just pointing this out in case we want to mention that setting here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops, i see the setting is mentioned already. lgtm!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nevermind, i got myself confused again. the current PR mentions sql.txn.read_committed_isolation.enabled which is true by default, but not sql.txn.repeatable_read_isolation.enabled which is false by default. given that we don't really mention repeatable read anywhere else in the docs, i'm not really sure how we want to discuss it here. i recall @dikshant mentioning he wanted to wait a bit before advertising that we support it (https://cockroachlabs.slack.com/archives/C051DMXEGMV/p1733255496192269?thread_ts=1733251940.956479&cid=C051DMXEGMV)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense -- I'm removing the row with REPEATABLE READ but leaving the one with SNAPSHOT.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In terms of the product decision to not mention REPEATABLE READ here, the same concerns would apply to mentioning SNAPSHOT. The usage of either of them is gated behind the sql.txn.repeatable_read_isolation.enabled/sql.txn.snapshot_isolation.enabled cluster setting, which are aliases of each other.

Copy link
Contributor Author

@taroface taroface Apr 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, got it! Amending.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Yeah good to leave out repeatable read for now.

@taroface taroface requested a review from florence-crl April 9, 2025 19:42
@florence-crl
Copy link
Contributor

deploy-preview is failing with

4:33:36 PM:   hash does not exist --- docs/v23.2/read-committed.html --> /docs/v23.2/transactions.html#aliases

I think this is the line in /v23.2/read-committed.md that has #aliases:

In v23.2, `sql.txn.read_committed_isolation.enabled` is `false` by default. As a result, `READ COMMITTED` transactions are [automatically upgraded to `SERIALIZABLE`]({% link {{ page.version.version }}/transactions.md %}#aliases) unless this setting is enabled. **This differs in v24.1 and later**, where `sql.txn.read_committed_isolation.enabled` is `true` by default.

Please fix the link. thanks

@taroface
Copy link
Contributor Author

transactions.html#aliases

Sorry! Fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants