diff --git a/_includes/sidebar-data-v20.1.json b/_includes/sidebar-data-v20.1.json index 5dfc3a6718b..6846261249e 100644 --- a/_includes/sidebar-data-v20.1.json +++ b/_includes/sidebar-data-v20.1.json @@ -1338,6 +1338,12 @@ "/${VERSION}/show-statistics.html" ] }, + { + "title": "SHOW SAVEPOINT STATUS", + "urls": [ + "/${VERSION}/show-savepoint-status.html" + ] + }, { "title": "SHOW TABLES", "urls": [ diff --git a/_includes/v20.1/misc/customizing-the-savepoint-name.md b/_includes/v20.1/misc/customizing-the-savepoint-name.md deleted file mode 100644 index 3608c3650b7..00000000000 --- a/_includes/v20.1/misc/customizing-the-savepoint-name.md +++ /dev/null @@ -1,7 +0,0 @@ - Set the `force_savepoint_restart` [session variable](set-vars.html#supported-variables) to `true` to enable using a custom name for the restart savepoint (for example, because you are using an ORM that wants to use its own names for savepoints). - -Once this variable is set, the [`SAVEPOINT`](savepoint.html) statement will accept any name for the savepoint, not just `cockroach_restart`. This allows compatibility with existing code that uses a single savepoint per transaction as long as that savepoint occurs before any statements that access data stored in non-virtual tables. - -{{site.data.alerts.callout_danger}} -The `force_savepoint_restart` variable changes the semantics of CockroachDB savepoints so that `RELEASE SAVEPOINT ` functions as a real commit. Note that the existence of this variable and its behavior does not change the fact that CockroachDB savepoints can only be used as a part of the transaction retry protocol. -{{site.data.alerts.end}} diff --git a/_includes/v20.1/misc/savepoint-limitations.md b/_includes/v20.1/misc/savepoint-limitations.md deleted file mode 100644 index 1232d1d3831..00000000000 --- a/_includes/v20.1/misc/savepoint-limitations.md +++ /dev/null @@ -1,3 +0,0 @@ -{{site.data.alerts.callout_danger}} -CockroachDB's [`SAVEPOINT`](savepoint.html) implementation does not support nested transactions (i.e., subtransactions). It is only used to handle [transaction retries](transactions.html#transaction-retries). -{{site.data.alerts.end}} diff --git a/_includes/v20.1/sql/diagrams/rollback_transaction.html b/_includes/v20.1/sql/diagrams/rollback_transaction.html index c34d5d12047..e981a160929 100644 --- a/_includes/v20.1/sql/diagrams/rollback_transaction.html +++ b/_includes/v20.1/sql/diagrams/rollback_transaction.html @@ -1,22 +1,17 @@ -
- - - - - - ROLLBACK - - - TO - - - SAVEPOINT - - - - cockroach_restart - - - - -
\ No newline at end of file +
+ + + + +ROLLBACK + + +TO + + +SAVEPOINT + + +savepoint_name + +
diff --git a/_includes/v20.1/sql/diagrams/show_savepoint_status.html b/_includes/v20.1/sql/diagrams/show_savepoint_status.html new file mode 100644 index 00000000000..7fc1c8fa52d --- /dev/null +++ b/_includes/v20.1/sql/diagrams/show_savepoint_status.html @@ -0,0 +1,15 @@ +
+ + + + +SHOW + + +SAVEPOINT + + +STATUS + + +
diff --git a/_includes/v20.1/sql/savepoint-ddl-rollbacks.md b/_includes/v20.1/sql/savepoint-ddl-rollbacks.md new file mode 100644 index 00000000000..96b6fd43145 --- /dev/null +++ b/_includes/v20.1/sql/savepoint-ddl-rollbacks.md @@ -0,0 +1,3 @@ +{{site.data.alerts.callout_danger}} +Rollbacks to savepoints over [DDL](https://en.wikipedia.org/wiki/Data_definition_language) statements are not yet supported. This is a known limitation and will be removed in a future version of CockroachDB. +{{site.data.alerts.end}} diff --git a/v20.1/advanced-client-side-transaction-retries.md b/v20.1/advanced-client-side-transaction-retries.md index da51aff0e3d..f97e951644f 100644 --- a/v20.1/advanced-client-side-transaction-retries.md +++ b/v20.1/advanced-client-side-transaction-retries.md @@ -24,15 +24,15 @@ A retryable transaction goes through the process described below, which maps to {% include copy-clipboard.html %} ~~~ sql > BEGIN; -- #1 -> SAVEPOINT cockroach_restart; -- #2 +> SAVEPOINT retry_savepoint; -- #2 -- ... various transaction statements ... -- #3 -> RELEASE SAVEPOINT cockroach_restart; -- #5 (Or #4, ROLLBACK, in case of retry error) +> RELEASE SAVEPOINT retry_savepoint; -- #5 (Or #4, ROLLBACK, in case of retry error) > COMMIT; ~~~ 1. The transaction starts with the [`BEGIN`](begin-transaction.html) statement. -2. The [`SAVEPOINT`](savepoint.html) statement declares the intention to retry the transaction in the case of contention errors. Note that CockroachDB's savepoint implementation does not support all savepoint functionality, such as nested transactions. It must be executed after [`BEGIN`](begin-transaction.html) but before the first statement that manipulates a database. +2. The [`SAVEPOINT`](savepoint.html) statement declares the intention to retry the transaction in the case of contention errors. It must be executed after [`BEGIN`](begin-transaction.html) but before the first statement that manipulates a database. In other words, it must be the outermost statement in an XXX: YOU ARE HERE. 3. The statements in the transaction are executed. @@ -46,10 +46,6 @@ A retryable transaction goes through the process described below, which maps to In some cases, the [`RELEASE SAVEPOINT`](release-savepoint.html) statement itself can fail with a retry error, mainly because transactions in CockroachDB only realize that they need to be restarted when they attempt to commit. If this happens, the retry error is handled as described in step 4. -## Customizing the savepoint name - -{% include {{ page.version.version }}/misc/customizing-the-savepoint-name.md %} - ## Examples For examples showing how to use [`SAVEPOINT`](savepoint.html) and the other statements described on this page to implement library support for a programming language, see the following: diff --git a/v20.1/begin-transaction.md b/v20.1/begin-transaction.md index e0f94bab96b..db872730979 100644 --- a/v20.1/begin-transaction.md +++ b/v20.1/begin-transaction.md @@ -53,7 +53,7 @@ Without modifying the `BEGIN` statement, the transaction uses `SERIALIZABLE` iso {% include copy-clipboard.html %} ~~~ sql -> SAVEPOINT cockroach_restart; +> SAVEPOINT my_savepoint; ~~~ {% include copy-clipboard.html %} @@ -68,7 +68,7 @@ Without modifying the `BEGIN` statement, the transaction uses `SERIALIZABLE` iso {% include copy-clipboard.html %} ~~~ sql -> RELEASE SAVEPOINT cockroach_restart; +> RELEASE SAVEPOINT my_savepoint; ~~~ {% include copy-clipboard.html %} @@ -89,7 +89,7 @@ You can set a transaction's priority to `LOW` or `HIGH`. {% include copy-clipboard.html %} ~~~ sql -> SAVEPOINT cockroach_restart; +> SAVEPOINT my_savepoint; ~~~ {% include copy-clipboard.html %} @@ -104,7 +104,7 @@ You can set a transaction's priority to `LOW` or `HIGH`. {% include copy-clipboard.html %} ~~~ sql -> RELEASE SAVEPOINT cockroach_restart; +> RELEASE SAVEPOINT my_savepoint; ~~~ {% include copy-clipboard.html %} diff --git a/v20.1/commit-transaction.md b/v20.1/commit-transaction.md index 14952b07b6c..5aec2d2935c 100644 --- a/v20.1/commit-transaction.md +++ b/v20.1/commit-transaction.md @@ -40,7 +40,7 @@ When using [advanced client-side transaction retries](advanced-client-side-trans {% include copy-clipboard.html %} ~~~ sql -> SAVEPOINT cockroach_restart; +> SAVEPOINT retry_savepoint; ~~~ {% include copy-clipboard.html %} @@ -55,7 +55,7 @@ When using [advanced client-side transaction retries](advanced-client-side-trans {% include copy-clipboard.html %} ~~~ sql -> RELEASE SAVEPOINT cockroach_restart; +> RELEASE SAVEPOINT retry_savepoint; ~~~ {% include copy-clipboard.html %} @@ -81,3 +81,4 @@ If you are using transactions that CockroachDB will [automatically retry](transa - [`RELEASE SAVEPOINT`](release-savepoint.html) - [`ROLLBACK`](rollback-transaction.html) - [`SAVEPOINT`](savepoint.html) +- [`SHOW SAVEPOINT STATUS`](show-savepoint-status.html) diff --git a/v20.1/follower-reads.md b/v20.1/follower-reads.md index 64baefa91a0..7dab5c4b221 100644 --- a/v20.1/follower-reads.md +++ b/v20.1/follower-reads.md @@ -61,7 +61,7 @@ BEGIN; SET TRANSACTION AS OF SYSTEM TIME experimental_follower_read_timestamp(); -SAVEPOINT cockroach_restart; +SAVEPOINT my_savepoint; SELECT ... SELECT ... @@ -102,7 +102,7 @@ To counteract this, you can issue all follower reads in explicit transactions se ```sql BEGIN PRIORITY HIGH AS OF SYSTEM TIME experimental_follower_read_timestamp(); -SAVEPOINT cockroach_restart; +SAVEPOINT my_savepoint; SELECT ... SELECT ... diff --git a/v20.1/online-schema-changes.md b/v20.1/online-schema-changes.md index 6e5ea97ee14..c68f69a0491 100644 --- a/v20.1/online-schema-changes.md +++ b/v20.1/online-schema-changes.md @@ -52,7 +52,7 @@ However, as of version v2.1, you can run schema changes inside the same transact {% include copy-clipboard.html %} ~~~ sql > BEGIN; - SAVEPOINT cockroach_restart; + SAVEPOINT my_savepoint; CREATE TABLE fruits ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), name STRING, @@ -62,7 +62,7 @@ However, as of version v2.1, you can run schema changes inside the same transact ALTER TABLE fruits ADD COLUMN inventory_count INTEGER DEFAULT 5; ALTER TABLE fruits ADD CONSTRAINT name CHECK (name IN ('apple', 'banana', 'orange')); SELECT name, color, inventory_count FROM fruits; - RELEASE SAVEPOINT cockroach_restart; + RELEASE SAVEPOINT my_savepoint; COMMIT; ~~~ @@ -139,10 +139,10 @@ The following statements fail due to [limited support for schema changes within ~~~ sql > CREATE TABLE foo (id INT PRIMARY KEY, name VARCHAR); BEGIN; - SAVEPOINT cockroach_restart; + SAVEPOINT my_savepoint; CREATE INDEX foo_idx ON foo (id, name); SELECT * from foo_idx; - RELEASE SAVEPOINT cockroach_restart; + RELEASE SAVEPOINT my_savepoint; COMMIT; ~~~ @@ -162,10 +162,10 @@ ROLLBACK ~~~ sql > CREATE TABLE foo (); BEGIN; - SAVEPOINT cockroach_restart; + SAVEPOINT my_savepoint; ALTER TABLE foo ADD COLUMN bar VARCHAR; ALTER TABLE foo ADD CONSTRAINT bar CHECK (foo IN ('a', 'b', 'c', 'd')); - RELEASE SAVEPOINT cockroach_restart; + RELEASE SAVEPOINT my_savepoint; COMMIT; ~~~ @@ -185,10 +185,10 @@ ROLLBACK ~~~ sql > CREATE TABLE foo (); BEGIN; - SAVEPOINT cockroach_restart; + SAVEPOINT my_savepoint; ALTER TABLE foo ADD COLUMN bar VARCHAR; SELECT bar FROM foo; - RELEASE SAVEPOINT cockroach_restart; + RELEASE SAVEPOINT my_savepoint; COMMIT; ~~~ diff --git a/v20.1/release-savepoint.md b/v20.1/release-savepoint.md index e4cc00b6359..1b0af456bc2 100644 --- a/v20.1/release-savepoint.md +++ b/v20.1/release-savepoint.md @@ -1,16 +1,16 @@ --- title: RELEASE SAVEPOINT -summary: Commit a transaction's changes once there are no retry errors with the RELEASE SAVEPOINT statement in CockroachDB. +summary: Commit a sub-transaction. toc: true --- -When using [advanced client-side transaction retries](advanced-client-side-transaction-retries.html), the `RELEASE SAVEPOINT` statement commits the transaction. +The `RELEASE SAVEPOINT` statement commits the [sub-transaction](transactions.html#sub-transactions) starting at the corresponding `SAVEPOINT` statement using the same savepoint name, including all its nested sub-transactions. -If statements in the transaction [generated any non-retry errors](transactions.html#error-handling), `RELEASE SAVEPOINT` is equivalent to [`ROLLBACK`](rollback-transaction.html), which aborts the transaction and discards all updates made by its statements. +The `RELEASE SAVEPOINT` statement is invalid after the sub-transaction has encountered an error. After an error, the [`ROLLBACK TO SAVEPOINT`](rollback-transaction.html#using-rollbacks-with-nested-savepoints) statement must be used instead. -Note that although issuing this statement commits the transaction, you must also issue a subsequent [`COMMIT`](commit-transaction.html) statement to prepare the connection for the next transaction. +When a (sub-)transaction encounters a retry error, the client should repeat `ROLLBACK TO SAVEPOINT` and the statements in the transaction until the statements complete without error, then issue `RELEASE`. -{% include {{ page.version.version }}/misc/savepoint-limitations.md %} +To completely remove the marker of a sub-transaction after it encounters an error and begin other work in the outer transaction, use [`ROLLBACK TO SAVEPOINT`](rollback-transaction.html#using-rollbacks-with-nested-savepoints) immediately followed by `RELEASE`. ## Synopsis @@ -26,11 +26,7 @@ No [privileges](authorization.html#assign-privileges) are required to release a Parameter | Description --------- | ----------- -name | The name of the savepoint. Defaults to `cockroach_restart`, but may be customized. For more information, see [Customizing the savepoint name](#customizing-the-savepoint-name). - -## Customizing the savepoint name - -{% include {{ page.version.version }}/misc/customizing-the-savepoint-name.md %} +name | The name of the savepoint. ## Examples @@ -40,25 +36,19 @@ After declaring a [`SAVEPOINT`](savepoint.html), commit the transaction with `RE {% include copy-clipboard.html %} ~~~ sql -> BEGIN; - -> SAVEPOINT cockroach_restart; - -> UPDATE products SET inventory = 0 WHERE sku = '8675309'; - -> INSERT INTO orders (customer, sku, status) VALUES (1001, '8675309', 'new'); - -> RELEASE SAVEPOINT cockroach_restart; - -> COMMIT; +BEGIN; +SAVEPOINT update_inventory; +UPDATE products SET inventory = 0 WHERE sku = '8675309'; +INSERT INTO orders (customer, sku, status) VALUES (1001, '8675309', 'new'); +RELEASE SAVEPOINT update_inventory; +COMMIT; ~~~ -{{site.data.alerts.callout_danger}}This example assumes you're using client-side intervention to handle transaction retries.{{site.data.alerts.end}} - ## See also - [Transactions](transactions.html) - [`SAVEPOINT`](savepoint.html) +- [`SHOW SAVEPOINT STATUS`](show-savepoint-status.html) - [`ROLLBACK`](rollback-transaction.html) - [`BEGIN`](begin-transaction.html) - [`COMMIT`](commit-transaction.html) diff --git a/v20.1/rollback-transaction.md b/v20.1/rollback-transaction.md index 3dc6c0f30f3..2227013fd3b 100644 --- a/v20.1/rollback-transaction.md +++ b/v20.1/rollback-transaction.md @@ -1,10 +1,16 @@ --- title: ROLLBACK -summary: Abort the current transaction, discarding all updates made by statements included in the transaction with the ROLLBACK statement in CockroachDB. +summary: Rolls back the current transaction or sub-transaction, discarding all transactional updates made by statements inside the transaction. toc: true --- -The `ROLLBACK` [statement](sql-statements.html) aborts the current [transaction](transactions.html), discarding all updates made by statements included in the transaction. +The `ROLLBACK` [statement](sql-statements.html) aborts the current [transaction](transactions.html) or [sub-transaction](transactions.html#sub-transactions), discarding all transactional updates made by statements included in the transaction. + +The base `ROLLBACK` syntax [rolls back the entire transaction](#rollback-a-transaction). + +The `ROLLBACK TO SAVEPOINT` syntax rolls back and restarts the [sub-transaction](transactions.html#sub-transactions) started at the corresponding `SAVEPOINT` statement. For more information, see [the documentation for `SAVEPOINT`](savepoint.html). + +{% include {{page.version.version}}/sql/savepoint-ddl-rollbacks.md %} When using [advanced client-side transaction retries](advanced-client-side-transaction-retries.html), use `ROLLBACK TO SAVEPOINT` to handle a transaction that needs to be retried (identified via the `40001` error code or `retry transaction` string in the error message), and then re-execute the statements you want the transaction to contain. @@ -22,10 +28,14 @@ No [privileges](authorization.html#assign-privileges) are required to rollback a Parameter | Description -----------|------------- - `TO SAVEPOINT cockroach_restart` | If using [advanced client-side transaction retries](advanced-client-side-transaction-retries.html), retry the transaction. You should execute this statement when a transaction returns a `40001` / `retry transaction` error. + `TO SAVEPOINT ` | If using [advanced client-side transaction retries](advanced-client-side-transaction-retries.html), retry the transaction. You should execute this statement when a transaction returns a `40001` / `retry transaction` error. ## Example +### Using rollbacks with nested savepoints + +For examples showing how to use `ROLLBACK` with nested savepoints, see [the `SAVEPOINT` documentation](savepoint.html). + ### Rollback a transaction Typically, an application conditionally executes rollbacks, but we can see their behavior by using `ROLLBACK` instead of `COMMIT` directly through SQL: @@ -77,15 +87,16 @@ To use [advanced client-side transaction retries](advanced-client-side-transacti {% include copy-clipboard.html %} ~~~ sql -> ROLLBACK TO SAVEPOINT cockroach_restart; +> ROLLBACK TO SAVEPOINT my_retry_savepoint; ~~~ For examples of retrying transactions in an application, check out the transaction code samples in our [Build an App with CockroachDB](build-an-app-with-cockroachdb.html) tutorials. ## See also +- [`SAVEPOINT`](savepoint.html) - [Transactions](transactions.html) - [`BEGIN`](begin-transaction.html) - [`COMMIT`](commit-transaction.html) -- [`SAVEPOINT`](savepoint.html) - [`RELEASE SAVEPOINT`](release-savepoint.html) +- [`SHOW SAVEPOINT STATUS`](show-savepoint-status.html) diff --git a/v20.1/savepoint.md b/v20.1/savepoint.md index b2f5fe4be51..7021f8b85c0 100644 --- a/v20.1/savepoint.md +++ b/v20.1/savepoint.md @@ -1,12 +1,12 @@ --- title: SAVEPOINT -summary: Identify your intent to retry aborted transactions with the SAVEPOINT statement in CockroachDB. +summary: Start a sub-transaction. toc: true --- -The `SAVEPOINT` statement defines the intent to retry [transactions](transactions.html) using the CockroachDB-provided function for client-side transaction retries. For more information, see [Transaction Retries](transactions.html#transaction-retries). +A savepoint is a marker that defines the beginning of a [sub-transaction](transactions.html#sub-transactions). This marker can be later used to commit or roll back just the effects of the sub-transaction without affecting the progress of the enclosing (sub-)transaction. Sub-transactions can be nested. -{% include {{ page.version.version }}/misc/savepoint-limitations.md %} +{% include {{page.version.version}}/sql/savepoint-ddl-rollbacks.md %} ## Synopsis @@ -22,17 +22,205 @@ No [privileges](authorization.html#assign-privileges) are required to create a s Parameter | Description --------- | ----------- -name | The name of the savepoint. Defaults to `cockroach_restart`, but may be customized. For more information, see [Customizing the savepoint name](#customizing-the-savepoint-name). +name | The name of the savepoint. -## Customizing the savepoint name +## Examples -{% include {{ page.version.version }}/misc/customizing-the-savepoint-name.md %} +The examples below use the following table: -## Example +{% include copy-clipboard.html %} +~~~ sql +CREATE TABLE kv (k INT PRIMARY KEY, v INT); +~~~ + +### Basic usage + +To establish a savepoint inside a transaction: + +{% include copy-clipboard.html %} +~~~ sql +SAVEPOINT foo; +~~~ + +{{site.data.alerts.callout_info}} +Due to the [rules for identifiers in our SQL grammar](keywords-and-identifiers.html#identifiers), `SAVEPOINT foo` and `SAVEPOINT Foo` define the same savepoint, whereas `SAVEPOINT "Foo"` defines another. +{{site.data.alerts.end}} + +To roll back a transaction partially to a previously established savepoint: + +{% include copy-clipboard.html %} +~~~ sql +ROLLBACK TO SAVEPOINT foo; +~~~ + +To forget a savepoint, and keep the effects of statements executed after the savepoint was established, use [`RELEASE SAVEPOINT`](release-savepoint.html): + +{% include copy-clipboard.html %} +~~~ sql +RELEASE SAVEPOINT foo; +~~~ + +For example, the transaction below will insert the values `(1,1)` and `(3,3)` into the table, but not `(2,2)`: + +{% include copy-clipboard.html %} +~~~ sql +BEGIN; +INSERT INTO kv VALUES (1,1); +SAVEPOINT my_savepoint; +INSERT INTO kv VALUES (2,2); +ROLLBACK TO SAVEPOINT my_savepoint; +INSERT INTO kv VALUES (3,3); +COMMIT; +~~~ + +### Nested savepoints -After you `BEGIN` the transaction, you must create the savepoint to identify that if the transaction contends with another transaction for resources and "loses", you intend to use [client-side transaction retries](transactions.html#transaction-retries). +Savepoints can be nested. [`RELEASE SAVEPOINT`](release-savepoint.html) and [`ROLLBACK TO SAVEPOINT`](rollback-transaction.html) can both refer to a savepoint "higher" in the nesting hierarchy. When this occurs, all of the savepoints "under" the nesting are automatically released / rolled back too. Specifically: -Applications using `SAVEPOINT` must also include functions to execute retries with [`ROLLBACK TO SAVEPOINT `](rollback-transaction.html#retry-a-transaction). +- When a previous savepoint is rolled back, the statements entered after that savepoint are also rolled back. + +- When a previous savepoint is released, it commits; the statements entered after that savepoint are also committed. + +### Multi-level rollback with `ROLLBACK` + +Savepoints can be arbitrarily nested, and rolled back to the outermost level so that every subsequent statement is rolled back. + +For example, this transaction does not insert anything into the table. Both `INSERT`s are rolled back: + +{% include copy-clipboard.html %} +~~~ sql +BEGIN; +SAVEPOINT foo; +INSERT INTO kv VALUES (5,5); +SAVEPOINT bar; +INSERT INTO kv VALUES (6,6); +ROLLBACK TO SAVEPOINT foo; +COMMIT; +~~~ + +### Multi-level commit with `RELEASE SAVEPOINT` + +Changes committed by releasing a savepoint commit all of the statements entered after that savepoint. + +For example, the following transaction inserts both `(2,2)` and `(4,4)` into the table when it releases the outermost savepoint: + +{% include copy-clipboard.html %} +~~~ sql +BEGIN; +SAVEPOINT foo; +INSERT INTO kv VALUES (2,2); +SAVEPOINT bar; +INSERT INTO kv VALUES (4,4); +RELEASE SAVEPOINT foo; +COMMIT; +~~~ + +### Multi-level rollback and commit in the same transaction + +Changes partially committed by a savepoint release can be rolled back by an outer savepoint. + +For example, the following transaction inserts only value `(5, 5)`. The values `(6,6)` and `(7,7)` are rolled back. + +{% include copy-clipboard.html %} +~~~ sql +BEGIN; +INSERT INTO kv VALUES (5,5); +SAVEPOINT foo; +INSERT INTO kv VALUES (6,6); +SAVEPOINT bar; +INSERT INTO kv VALUES (7,7); +RELEASE SAVEPOINT bar; +ROLLBACK TO SAVEPOINT foo; +COMMIT; +~~~ + +### Savepoint name visibility + +The name of a savepoint that was rolled back over is no longer visible afterward. + +For example, in the transaction below, the name "bar" is not visible after it was rolled back over: + +{% include copy-clipboard.html %} +~~~ sql +BEGIN; +SAVEPOINT foo; +SAVEPOINT bar; +ROLLBACK TO SAVEPOINT foo; +RELEASE SAVEPOINT bar; +COMMIT; +~~~ + +~~~ +ERROR: savepoint bar does not exist +SQLSTATE: 3B001 +~~~ + +The [SQL client](cockroach-sql.html) prompt will now display an error state, which you can clear by entering [`ROLLBACK`](rollback-transaction.html): + +{% include copy-clipboard.html %} +~~~ sql +? ERROR> ROLLBACK; +~~~ + +~~~ +ROLLBACK +~~~ + +#### Savepoints and prepared statements + +Prepared statements (`PREPARE` / `EXECUTE`) are not transactional. Therefore, prepared statements are not invalidated upon savepoint rollback. As a result, the prepared statement was saved and executed inside the transaction, despite the rollback to the prior savepoint: + +{% include copy-clipboard.html %} +~~~ sql +BEGIN; +SAVEPOINT foo; +PREPARE bar AS SELECT 1; +ROLLBACK TO SAVEPOINT foo; +EXECUTE bar; +COMMIT; +~~~ + +~~~ + ?column? +------------ + 1 +(1 row) +~~~ + + + +### Savepoints for client-side transaction retries + +If you intend to implement [advanced client-side transaction retries](advanced-client-side-transaction-retries.html), after you `BEGIN` the transaction, you must create an outermost savepoint. This will identify that if the transaction contends with another transaction for resources and "loses", you intend to use [client-side transaction retries](transactions.html#transaction-retries). + +Applications using `SAVEPOINT` for client-side transaction retries must also include functions to execute retries with [`ROLLBACK TO SAVEPOINT `](rollback-transaction.html#retry-a-transaction). + +A savepoint used for client-side transaction retries must be the outermost savepoint in a transaction; it cannot be nested inside other savepoints. {% include copy-clipboard.html %} ~~~ sql @@ -41,7 +229,7 @@ Applications using `SAVEPOINT` must also include functions to execute retries wi {% include copy-clipboard.html %} ~~~ sql -> SAVEPOINT cockroach_restart; +> SAVEPOINT my_retry_savepoint; ~~~ {% include copy-clipboard.html %} @@ -56,7 +244,7 @@ Applications using `SAVEPOINT` must also include functions to execute retries wi {% include copy-clipboard.html %} ~~~ sql -> RELEASE SAVEPOINT cockroach_restart; +> RELEASE SAVEPOINT my_retry_savepoint; ~~~ {% include copy-clipboard.html %} @@ -64,12 +252,32 @@ Applications using `SAVEPOINT` must also include functions to execute retries wi > COMMIT; ~~~ +### Showing savepoint status + +Use the [`SHOW SAVEPOINT STATUS`](show-savepoint-status.html) statement to see how many savepoints are active in the current transaction: + +{% include copy-clipboard.html %} +~~~ sql +SHOW SAVEPOINT STATUS; +~~~ + +~~~ + savepoint_name | is_initial_savepoint +-----------------+----------------------- + foo | false + bar | false +(2 rows) +~~~ + +Note that the `is_initial_savepoint` column will be true if the savepoint is the outermost savepoint in the transaction. + ## See also -- [Transactions](transactions.html) +- [`SHOW SAVEPOINT STATUS`](show-savepoint-status.html) - [`RELEASE SAVEPOINT`](release-savepoint.html) - [`ROLLBACK`](rollback-transaction.html) - [`BEGIN`](begin-transaction.html) - [`COMMIT`](commit-transaction.html) +- [Transactions](transactions.html) - [Retryable transaction example code in Java using JDBC](build-a-java-app-with-cockroachdb.html) - [CockroachDB Architecture: Transaction Layer](architecture/transaction-layer.html) diff --git a/v20.1/set-transaction.md b/v20.1/set-transaction.md index 7cbab1e9941..fefbe24cfe3 100644 --- a/v20.1/set-transaction.md +++ b/v20.1/set-transaction.md @@ -44,7 +44,7 @@ CockroachDB now only supports `SERIALIZABLE` isolation, so transactions can no l {% include copy-clipboard.html %} ~~~ sql -> SAVEPOINT cockroach_restart; +> SAVEPOINT my_savepoint; ~~~ {% include copy-clipboard.html %} @@ -59,7 +59,7 @@ CockroachDB now only supports `SERIALIZABLE` isolation, so transactions can no l {% include copy-clipboard.html %} ~~~ sql -> RELEASE SAVEPOINT cockroach_restart; +> RELEASE SAVEPOINT my_savepoint; ~~~ {% include copy-clipboard.html %} diff --git a/v20.1/show-savepoint-status.md b/v20.1/show-savepoint-status.md new file mode 100644 index 00000000000..aa97fbf8fdd --- /dev/null +++ b/v20.1/show-savepoint-status.md @@ -0,0 +1,71 @@ +--- +title: SHOW SAVEPOINT STATUS +summary: The SHOW SAVEPOINT STATUS statement lists the active savepoints in the current transaction. +toc: true +--- + +The `SHOW SAVEPOINT STATUS` [statement](sql-statements.html) lists the active [savepoints](savepoint.html) in the current [transaction](transactions.html). + +## Required privileges + +No [privileges](authorization.html#assign-privileges) are required to create or show a savepoint. However, privileges are required for each statement within a transaction. + +## Synopsis + +
+ {% include {{ page.version.version }}/sql/diagrams/show_savepoint_status.html %} +
+ +## Response + +The following fields are returned for each savepoint. + +Field | Description +------|------------ +`savepoint_name` | The name of the savepoint. +`is_initial_savepoint` | Whether the savepoint is the outermost savepoint in the transaction. + +## Example + +First, open a [transaction](transactions.html) using [`BEGIN`](begin-transaction.html), and create a [sub-transaction](transactions.html#sub-transactions) using a [savepoint](savepoint.html): + +{% include copy-clipboard.html %} +~~~ sql +BEGIN; +SAVEPOINT foo; +~~~ + +Next, use the `SHOW SAVEPOINT STATUS` statement to list the active savepoints in the current sub-transaction. + +{% include copy-clipboard.html %} +~~~ sql +SHOW SAVEPOINT STATUS; +~~~ + +~~~ + savepoint_name | is_initial_savepoint +-----------------+----------------------- + foo | true +(1 row) +~~~ + +Currently, there is only one savepoint. + +We can commit this sub-transaction by issuing the [`RELEASE SAVEPOINT`](release-savepoint.html) statement. Then, we clear the connection for the next transaction by issuing a [`COMMIT`](commit-transaction.html) statement. + +{% include copy-clipboard.html %} +~~~ sql +RELEASE SAVEPOINT foo; +COMMIT; +~~~ + +If we did not want to commit this sub-transaction, but restart it instead, we would have issued a [`ROLLBACK TO SAVEPOINT`](rollback-transaction.html#using-rollbacks-with-nested-savepoints). + +## See also + +- [`SAVEPOINT`](savepoint.html) +- [`RELEASE SAVEPOINT`](release-savepoint.html) +- [`ROLLBACK`](rollback-transaction.html) +- [`BEGIN`](begin-transaction.html) +- [`COMMIT`](commit-transaction.html) +- [Transactions](transactions.html) diff --git a/v20.1/transactions.md b/v20.1/transactions.md index feecd97c873..82400cd6db6 100644 --- a/v20.1/transactions.md +++ b/v20.1/transactions.md @@ -41,11 +41,11 @@ To use [advanced client-side transaction retries](advanced-client-side-transacti ~~~ sql > BEGIN; -> SAVEPOINT cockroach_restart; +> SAVEPOINT my_retry_savepoint; -> RELEASE SAVEPOINT cockroach_restart; +> RELEASE SAVEPOINT my_retry_savepoint; > COMMIT; ~~~ @@ -166,6 +166,14 @@ Transactions in CockroachDB lock data resources that are written during their ex For more details about transaction contention and best practices for avoiding contention, see [Understanding and Avoiding Transaction Contention](performance-best-practices-overview.html#understanding-and-avoiding-transaction-contention). +## Sub-transactions + +New in v20.1: CockroachDB supports the nesting of transactions using [savepoints](savepoint.html). These nested transactions are also known as sub-transactions. + +Just as [`COMMIT`](commit-transaction.html) and [`ROLLBACK`](rollback-transaction.html) are used to commit and discard entire transactions, respectively, [`RELEASE SAVEPOINT`](release-savepoint.html) and [`ROLLBACK TO SAVEPOINT`](rollback-transaction.html#using-rollbacks-with-nested-savepoints) are used to commit and discard sub-transactions. + +For more information, including examples showing how to use savepoints to create sub-transactions, see [the savepoints documentation](savepoint.html#examples). + ## Transaction priorities Every transaction in CockroachDB is assigned an initial **priority**. By default, that priority is `NORMAL`, but for transactions that should be given preference in [high-contention scenarios](performance-best-practices-overview.html#understanding-and-avoiding-transaction-contention), the client can set the priority within the [`BEGIN`](begin-transaction.html) statement: