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

sql: introduce preliminary support for savepoints #43051

Closed
wants to merge 2 commits into from

Conversation

knz
Copy link
Contributor

@knz knz commented Dec 9, 2019

Informs #10735
This implementation corresponds to compatibility level L1 in the RFC.

This PR defines:

  • the savepoint name stack-like scoping to implement nesting
  • the savepoint lookup and rewind logic
  • the separation of logic between restart and "regular" savepoints
  • working logic to release and roll back regular savepoints when no errors have occurred

What is not supported:

  • defining restart savepoints "under" regular savepoints (out of scope according to RFC)
  • rolling back to a regular savepoint over an error (this is planned for a later PR)

@knz knz added the do-not-merge bors won't merge a PR with this label. label Dec 9, 2019
@cockroach-teamcity
Copy link
Member

This change is Reviewable

@knz knz force-pushed the 20191208-sql-savepoints branch 2 times, most recently from 76904f0 to 43d3b64 Compare December 10, 2019 21:28
@knz knz changed the title [WIP] sql: introduce preliminary support for savepoints sql: introduce preliminary support for savepoints Dec 10, 2019
@knz knz removed the do-not-merge bors won't merge a PR with this label. label Dec 10, 2019
@knz
Copy link
Contributor Author

knz commented Dec 10, 2019

Some experiment about the current DDL behavior:

GOOD:

> begin;
  savepoint foo;
  create table t(x int);
  insert into t(x) values (1);
  rollback to savepoint foo;
  commit;
COMMIT

> select * from t;
ERROR: relation "t" does not exist
SQLSTATE: 42P01

BAD:

> begin; 
  savepoint foo; 
  create table t(x int); 
  rollback to savepoint foo;
ROLLBACK
> insert into t(x) values (1);
INSERT

(Bad because the create is rolled back so insert should fail to see the table)

But then:

> commit;
COMMIT

> select * from t;
ERROR: relation "t" does not exist
SQLSTATE: 42P01

So at least the creation gets eventually rolled back.

@knz
Copy link
Contributor Author

knz commented Feb 5, 2020

This PR is ready for initial review.

Here are the pieces missing before it can merge:

However I think the general structure of the code is ready for review and I'd appreciate the early feedback.

craig bot pushed a commit that referenced this pull request Feb 5, 2020
43828: backupccl: add full cluster restore r=pbardea a=pbardea

This commit adds the ability to entirely restore a full cluster backup.
This includes replacing the contents of some system tables to match the
data in the backup. Full cluster restore can be used using the `RESTORE
FROM ...` syntax and is expected to be run on a new cluster with no user
data.

Release note (enterprise change): Add full cluster restore feature which
restores all the information contained in a full cluster backup. This
includes all of the user data as well as relevant data from system
tables. It is expected to be run on a new cluster with no user data.

44684: sql: move the existing savepoint logic to a separate file r=yuzefovich a=knz

This commit re-organizes the code without any functional change.

(Split from #43051 for ease of review.)

Co-authored-by: Paul Bardea <pbardea@gmail.com>
Co-authored-by: Raphael 'kena' Poss <knz@thaumogen.net>
@knz knz mentioned this pull request Feb 6, 2020
@knz knz force-pushed the 20191208-sql-savepoints branch 2 times, most recently from 99a5145 to 84fed1b Compare February 7, 2020 00:08
@knz
Copy link
Contributor Author

knz commented Feb 7, 2020

The failed tests show that the restart savepoint is erroneously dropped and becomes unusable after a first RELEASE SAVEPOINT cockroach_restart encounters a retry error.

This is is because COMMIT implicitly drops all savepoints, and RELEASE SAVEPOINT cockroach_restart reuses the COMMIT code.

I'll split the commit code in two to fix.

Copy link
Contributor

@andreimatei andreimatei left a comment

Choose a reason for hiding this comment

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

There's a lot of distinction in this PR between "restart" and non-restart savepoints. I wonder if there's a reason for this distinction. The only reason I can think of is that in the case of rolling back to cockroach_restart, we definitely don't want to clean up intents, whereas for everything else we might want to clean them up. Except with the current implementation, we never clean up any intents (right)? So I wonder if we really need the distinction. Because if we don't, it looks to me like a lot of code would be simpler.

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @andreimatei, @knz, and @nvanbenschoten)


pkg/sql/conn_executor_savepoints.go, line 260 at r5 (raw file):

// special "restart" semantics.
func (ex *connExecutor) isRestartSavepoint(savepoint tree.Name) bool {
	if ex.sessionData.ForceSavepointRestart {

Does this ForceSavepointRestart session var still serve a purpose?


pkg/sql/conn_executor_savepoints.go, line 261 at r5 (raw file):

func (ex *connExecutor) isRestartSavepoint(savepoint tree.Name) bool {
	if ex.sessionData.ForceSavepointRestart {
		// The session sxetting force_savepoint_restart implies that all

sxetting

Copy link
Contributor Author

@knz knz left a comment

Choose a reason for hiding this comment

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

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @andreimatei and @nvanbenschoten)


pkg/sql/conn_executor_savepoints.go, line 260 at r5 (raw file):

Previously, andreimatei (Andrei Matei) wrote…

Does this ForceSavepointRestart session var still serve a purpose?

Unfortunately, yes. There's some ORM out there (presumably, Spring?) where the app cannot customize the identifiers generated for savepoints. With that ORM the only way to implement a retry loop is to make all savepoints retry savepoints.

I did push back against it with Jordan and andy but they would like to decouple the development of a specific adapter for that ORM from the savepoint work. That sounded reasonable to me, so I want to keep that logic here until the separate AppRel work makes progress.


pkg/sql/conn_executor_savepoints.go, line 261 at r5 (raw file):

Previously, andreimatei (Andrei Matei) wrote…

sxetting

Done.

Copy link
Contributor

@andreimatei andreimatei left a comment

Choose a reason for hiding this comment

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

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @andreimatei, @knz, and @nvanbenschoten)


pkg/sql/conn_executor_savepoints.go, line 260 at r5 (raw file):

Previously, knz (kena) wrote…

Unfortunately, yes. There's some ORM out there (presumably, Spring?) where the app cannot customize the identifiers generated for savepoints. With that ORM the only way to implement a retry loop is to make all savepoints retry savepoints.

I did push back against it with Jordan and andy but they would like to decouple the development of a specific adapter for that ORM from the savepoint work. That sounded reasonable to me, so I want to keep that logic here until the separate AppRel work makes progress.

I understand but I'm still hoping that the special treatment of cockroach_restart can also go away :)

Copy link
Contributor Author

@knz knz left a comment

Choose a reason for hiding this comment

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

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @andreimatei and @nvanbenschoten)


pkg/sql/conn_executor_savepoints.go, line 260 at r5 (raw file):

Previously, andreimatei (Andrei Matei) wrote…

I understand but I'm still hoping that the special treatment of cockroach_restart can also go away :)

I hope so too. But baby steps. I want to get to that L1 step in the RFC then also L2 (error recovery) and then we'll talk about this again.

Release note (sql change): CockroachDB now collects separate sets of
metrics for usage of SAVEPOINT: one set for regular SQL savepoints and
one set for uses dedicated to CockroachDB's client-side transaction
retry protocol.
This commit introduces support for regular SQL savepoints in the
executor.

The following is supported:

- recognizing the SAVEPOINT / ROLLBACK TO SAVEPOINT / RELEASE
  SAVEPOINT statements even when the savepoint name is not
  "cockroach_restart".
- maintaining a list of current active savepoints, and detect
  when SAVEPOINT and RELEASE/ROLLBACK are mismatched.
- issue the `GetSavepoint()` / `RollbackToSavepoint()` /
  `ReleaseSavepoint()` API calls to the KV layers.
- enforce that `cockroarch_restart` (and retry savepoints in general)
  are not started "under" a regular savepoint.

What is not supported yet:

- Rejecting ROLLBACK after a DDL statement has executed.
- ROLLBACK when the txn is aborted (i.e. after an error).

Release note (sql change): CockroachDB now provides
rudimentary (incomplete) and experimental support for SQL savepoints.

Release note (sql change): CockroachDB supports a new statement `SHOW
SAVEPOINT STATUS` which reveals the current stack of active
savepoints. This can be used to teach savepoint usage.
@knz knz requested a review from a team as a code owner February 15, 2020 21:39
@knz
Copy link
Contributor Author

knz commented Feb 15, 2020

The DDL blocking logic is now ready.
I have added numerous tests and transferred a few thing from logic tests to the new datadriven-based TestSavepoints.

RFAL. Note that I plan to implement error recovery in a subsequent PR.

Copy link
Contributor

@andreimatei andreimatei left a comment

Choose a reason for hiding this comment

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

Only if you're curious, I've been trying my hand over here: https://github.com/andreimatei/cockroach/commits/pr/43051
I think the code is getting there, but it's not ready - I seem to have broken something in one of the new tests.

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @andreimatei and @nvanbenschoten)

@knz
Copy link
Contributor Author

knz commented Mar 6, 2020

subsumed by #45566

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.

3 participants