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

rfcs: SQL savepoints #41569

Merged
merged 1 commit into from
Mar 19, 2020
Merged

rfcs: SQL savepoints #41569

merged 1 commit into from
Mar 19, 2020

Conversation

knz
Copy link
Contributor

@knz knz commented Oct 14, 2019

Informs #10735
Fixes #46075

Release justification: doc only change

Latest edits found at: https://github.com/knz/cockroach/blob/20191014-rfc-savepoints/docs/RFCS/20191014_savepoints.md

@knz knz requested a review from a team as a code owner October 14, 2019 15:54
@cockroach-teamcity
Copy link
Member

This change is Reviewable

@knz
Copy link
Contributor Author

knz commented Oct 14, 2019

cc @andreimatei

Copy link
Contributor

@bdarnell bdarnell left a comment

Choose a reason for hiding this comment

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

Questions about requirements: Do the anticipated uses of nested transactions involve schema changes? Do we need to support transactions that go through many savepoint/rollback cycles (which might lead to accumulated metadata in some implementations)?

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained

@knz
Copy link
Contributor Author

knz commented Oct 14, 2019 via email

@knz
Copy link
Contributor Author

knz commented Oct 14, 2019 via email

@knz
Copy link
Contributor Author

knz commented Oct 14, 2019

FWIW I checked and pg supports DDL under savepoints and rolls them back appropriately:

kena=> begin; \
  savepoint foo; \
  create table u(x int); \
  rollback to savepoint foo; \
  create table u(w int); \
  insert into u(x) values (1); \
commit;
BEGIN
SAVEPOINT
CREATE TABLE
ROLLBACK
CREATE TABLE
ERROR:  column "x" of relation "u" does not exist
LINE 1: insert into u(x) values (1);
                      ^
ROLLBACK
kena=>

@knz
Copy link
Contributor Author

knz commented Oct 14, 2019

One idea to consider that will get us the correct functional semantics at the expense of performance, is to disable descriptor caching across statements under a savepoint (multiple accesses to the same savepoint inside a single statement using a cache would still be OK since they would use the same sequence number).

@knz
Copy link
Contributor Author

knz commented Oct 14, 2019

@andreimatei and I just chatted and that invalidates my idea above. DDL inside a txn installs transient state in the SQL executor, beyond what's stored in KV. That would need to be rolled back, which would be complicated.

The next action item is thus to ascertain what specific requirements we have from users. That's what @jordanlewis and @awoods187 should help with:

  • do users expect to do DDL under savepoints
  • do the interesting test suites do so too
  • what about temp table usage under savepoints, is this a thing in the target use cases and is this a requirement for the work

@knz
Copy link
Contributor Author

knz commented Oct 14, 2019

FWIW I'm kickstarting a hibernate test run now to gather all failed test outputs related to savepoints. It's going to take several hours.

@knz
Copy link
Contributor Author

knz commented Oct 15, 2019

filed #41612 for the storage work

@knz
Copy link
Contributor Author

knz commented Oct 15, 2019

Input from team meeting:

@knz knz force-pushed the 20191014-rfc-savepoints branch 7 times, most recently from 0ccd8b1 to c0fbd56 Compare October 16, 2019 22:14
Copy link
Contributor

@awoods187 awoods187 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 @knz)


docs/RFCS/20191014_savepoints.md, line 4 at r1 (raw file):

- Status: draft
- Start Date: 2019-10-14
- Authors: andrei knz

nit ,


docs/RFCS/20191014_savepoints.md, line 37 at r1 (raw file):

The proposal here also incidentally addresses CockroachDB's own
Halloween problem (issue #28842) without additional work.

I couldn't see in the doc how this was the case


docs/RFCS/20191014_savepoints.md, line 117 at r1 (raw file):

This inserts 1 into u and 'a' into t. The table `t` with an INT column
does not exist after the transaction commits.

How does this work with our own limited support for schema changes inside transactions? As I understand it, the schema change is applied after the transaction commits. What if instead of rolling back an entire schema change you rollback some of the data written to schema changed table?


docs/RFCS/20191014_savepoints.md, line 199 at r1 (raw file):

	RELEASE SAVEPOINT bar; -- error: savepoint "bar" does not exist
COMMIT;

I assume this will result in no values inserted since it rollsback to foo?


docs/RFCS/20191014_savepoints.md, line 211 at r1 (raw file):

COMMIT;

So this would insert 1 and 2?


docs/RFCS/20191014_savepoints.md, line 249 at r1 (raw file):

(i.e. the second insert succeeds even though the first insert encountered an error)

so basically if you become aware that you made a mistake you can rollback your mistake and still continue with the transaction. You do not need a new transaction.

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 @awoods187)


docs/RFCS/20191014_savepoints.md, line 37 at r1 (raw file):

Previously, awoods187 (Andy Woods) wrote…

I couldn't see in the doc how this was the case

It's incidental so I'm not sure it deserves a particular explanation.


docs/RFCS/20191014_savepoints.md, line 117 at r1 (raw file):

Previously, awoods187 (Andy Woods) wrote…

How does this work with our own limited support for schema changes inside transactions? As I understand it, the schema change is applied after the transaction commits. What if instead of rolling back an entire schema change you rollback some of the data written to schema changed table?

That part is rolled back, and the rest remains.
Do you have an example in mind which we could use here to clarify?


docs/RFCS/20191014_savepoints.md, line 199 at r1 (raw file):

Previously, awoods187 (Andy Woods) wrote…

I assume this will result in no values inserted since it rollsback to foo?

Correct.


docs/RFCS/20191014_savepoints.md, line 211 at r1 (raw file):

Previously, awoods187 (Andy Woods) wrote…

So this would insert 1 and 2?

Yes.


docs/RFCS/20191014_savepoints.md, line 249 at r1 (raw file):

Previously, awoods187 (Andy Woods) wrote…

so basically if you become aware that you made a mistake you can rollback your mistake and still continue with the transaction. You do not need a new transaction.

Correct, yes. This is what ORMs and object-oriented apps do.

@knz knz force-pushed the 20191014-rfc-savepoints branch 2 times, most recently from 8ae7f3a to 77dda89 Compare October 16, 2019 23:29
@tbg tbg requested a review from awoods187 October 17, 2019 09:42
craig bot pushed a commit that referenced this pull request Dec 3, 2019
42668: sql: add precision support for TIME/TIMETZ r=otan a=otan

Refs: #32565
Refs: #26097 

Adding support for precision for both TIME and TIMETZ. This also
includes threading through some extra parsing syntax for TIMETZ.

ALTER TABLE between TIME and TIMETZ not supported as they have different
representations.

Release note (sql change): This PR adds new support for precision for
TIME types (e.g. TIME(3) will truncate to milliseconds). Previously this
would raise syntax errors.

42864: rfcs: new RFC on fixing the halloween problem r=knz a=knz

I am splitting this RFC away from the [RFC on savepoints](#41569) because I know recognize it is a different problem with an orthogonal solution.

https://github.com/knz/cockroach/blob/20191129-rfc-halloween/docs/RFCS/20191014_halloween.md

There is no new idea in this text (I copy-pasted the text from the other RFC) and the implementation PRs are already out, so if the reviewers are satisfied I would gladly already merge the RFC as in-progress or completed.

Co-authored-by: Oliver Tan <otan@cockroachlabs.com>
Co-authored-by: Raphael 'kena' Poss <knz@thaumogen.net>
craig bot pushed a commit that referenced this pull request Jan 20, 2020
42862: sql: make SQL statements operate on a read snapshot r=andreimatei a=knz

Fixes #33473.
Fixes #28842.
Informs #41569 and #42864.

Previously, all individual KV reads performed by a SQL statement were
able to observe the most recent KV writes that it performed itself.

This is in violation of PostgreSQL's dialect semantics, which mandate
that statements can only observe data as per a read snapshot taken at
the instant a statement begins execution.

Moreover, this invalid behavior causes a real observable bug: a
statement that reads and writes to the same table may never complete,
as the read part may become able to consume the rows that it itself
writes. Or worse, it could cause logical operations to be performed
multiple times: https://en.wikipedia.org/wiki/Halloween_Problem

This patch fixes it by exploiting the new KV `Step()` API which
decouples the read and write sequence numbers.

The fix is not complete however; additional sequence points must also
be introduced prior to FK existence checks and cascading actions. See
#42864 and #33475 for details.

For now, this patch excludes any mutation that involves a foreign key
from the new (fixed) semantics. When a mutation involves a FK, the
previous (broken) semantics still apply.

Release note (bug fix): SQL mutation statements that target tables
with no foreign key relationships now correctly read data as per the
state of the database when the statement started execution. This is
required for compatibility with PostgreSQL and to ensure deterministic
behavior when certain operations are parallelized. Prior to this fix,
a statement [could incorrectly operate multiple
times](https://en.wikipedia.org/wiki/Halloween_Problem) on data that
itself was writing, and potentially never terminate. This fix is
limited to tables without FK relationships, and for certain operations
on tables with FK relationships; in other cases, the fix is not
active and the bug is still present. A full fix will be provided
in a later release.


Co-authored-by: Raphael 'kena' Poss <knz@thaumogen.net>
@knz
Copy link
Contributor Author

knz commented Feb 6, 2020

I have updated the RFC based on learnings so far (current impl PR #43051).
I have removed several paragraphs that are now irrelevant.

I also have added a new section that summarizes the real work to be done (including all the items that I didn't perceive back in October): Savepoint and rollback semantics

Then I also produced a layering of the work into multiple "compatibility levels", which will enable tracking progress towards the release: Layering of work

@knz knz force-pushed the 20191014-rfc-savepoints branch 4 times, most recently from b1cb73d to e405ff2 Compare February 6, 2020 14:32
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, @awoods187, @bdarnell, @irfansharif, @knz, @nvanbenschoten, and @tbg)


docs/RFCS/20191014_savepoints.md, line 381 at r9 (raw file):

- L4: rewind over DDL statements that don't create jobs.
- L5: rewind over DDL statements that creates jobs.
- L6: rewind over retry errors that are not aborts.

I think L6 might simply mean restoring the txn's old epoch. Perhaps it won't just work because of assumptions we might have made about the epoch not going backwards, I'm not sure. But if it just works, I would move up L6. In fact I'd generally move L6 up because without it I think savepoints will be hard to use in practice; having to handle the case in which rollbacks fail seems like a big burden on applications.
Transactions that do schema changes I personally don't care about very much.


docs/RFCS/20191014_savepoints.md, line 389 at r9 (raw file):

| Situation                                                                       | L1                   | L2                             | L3                                           | L4                                           | L5                         | L6                                |
|---------------------------------------------------------------------------------|----------------------|--------------------------------|----------------------------------------------|----------------------------------------------|----------------------------|-----------------------------------|
| Txn state "open", read-only so far                                              | ok, rewind KV writes | ditto L1                       | ditto L1                                     | ditto L1                                     | ditto L1                   | ditto L1                          |

the "read-only so far" doesn't seem to jibe with "rewind KV writes"


docs/RFCS/20191014_savepoints.md, line 408 at r9 (raw file):

reports that it is not in error (i.e. the error is SQL-only).

L3: whitelist certain KV errors and call a (new) method on client.Txn

"Certain KV errors"? Not all the non-retriable ones?
I was thinking that we wouldn't particularly look at any errors; we'd just be looking at the transaction proto to see its state.

But now I'm thinking that there's also ambiguous errors coming from a commit to worry about. Or is the plan for those to dissallow rolling back to a savepoint after attempting a COMMIT sql statement in general?

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, @awoods187, @bdarnell, @irfansharif, @nvanbenschoten, and @tbg)


docs/RFCS/20191014_savepoints.md, line 511 at r5 (raw file):

Previously, RaduBerinde wrote…

Thanks. Agree with your example and the overall point, not so much with the "common" characterization. I think simple inserts tend to be more common (and they allow this optimization, short of self-ref). Updates which change a foreign key column are more rare I believe (as an example, TPCC has none, you never change the warehouse or whatever after you insert a row).

Thanks point taken.


docs/RFCS/20191014_savepoints.md, line 780 at r6 (raw file):

Previously, andreimatei (Andrei Matei) wrote…

It absolutely can. It's going to fail every KV request from then on, but that doesn't matter. A SQL client would detect the subsequent requests and decide (on its own, without help from TxnCoordSender) to abandon the txn

Perhaps we're discussing semantics, but not returning an error here from the leaf to the root is not an option (or at least I don't see how it would be). The current statement that's being executed needs to get an error. We can't pretend that reads were successful and didn't return any results.

I removed that section from the RFC (into the TCS tech note).


docs/RFCS/20191014_savepoints.md, line 974 at r6 (raw file):

Previously, andreimatei (Andrei Matei) wrote…

Currently, this is any non-retriable error.
I think the particular example you give is not the best for the reader - it's true that BatchTimestampBeforeGCError is not retriable, but one might think/argue it should be (like other "pushes"). I'd use duplicate key error or something like that.

ditto


docs/RFCS/20191014_savepoints.md, line 1005 at r6 (raw file):

Previously, andreimatei (Andrei Matei) wrote…

Turns out we have https://reviewable.io/reviews/cockroachdb/cockroach/35140 in flight which gets rid of this limitation.

Thanks for figuring this out.


docs/RFCS/20191014_savepoints.md, line 1007 at r7 (raw file):

Previously, andreimatei (Andrei Matei) wrote…

s/two/three :)

moved to tech note


docs/RFCS/20191014_savepoints.md, line 1010 at r7 (raw file):

Previously, andreimatei (Andrei Matei) wrote…

I think it'd be useful in these paragraphs to be more clear about what the different "operations" are in the different contexts. Here, it's a "batch" or a "request" (or a BatchRequest :) ). In the txn restart bullet before, it's a statement (or more generally a prefix of a transaction)

ditto


docs/RFCS/20191014_savepoints.md, line 1037 at r7 (raw file):

Previously, andreimatei (Andrei Matei) wrote…

Pushes are also generally handled this way. Like the deferred WTOE, they're not errors - they're just updates to the transaction's timestamp field, which get turned to retriable errors at EndTransaction time.

And as per our side conversations, it turns out that currently WTOE are actually never deferred (and I want to make sure they stay that way).

Moved to TCS t ech note.


docs/RFCS/20191014_savepoints.md, line 736 at r8 (raw file):

What error other than a TransactionAbortedError cannot be recovered by a savepoint rollback? It seems to me that everything can be recovered from. The savepoint is supposed to perfectly capture the state of the transaction at the point where it was created, isn't it?

  • assertion errors presumably leaves txns in an unknown state and the conservative decision is to let the txn abort with no further operations.
  • I would recommend that storage errors (corruptions etc) don't let apps paper over them with a rollback

docs/RFCS/20191014_savepoints.md, line 381 at r9 (raw file):

Previously, andreimatei (Andrei Matei) wrote…

I think L6 might simply mean restoring the txn's old epoch. Perhaps it won't just work because of assumptions we might have made about the epoch not going backwards, I'm not sure. But if it just works, I would move up L6. In fact I'd generally move L6 up because without it I think savepoints will be hard to use in practice; having to handle the case in which rollbacks fail seems like a big burden on applications.
Transactions that do schema changes I personally don't care about very much.

Good point. Added a sentence to clarify here and below.


docs/RFCS/20191014_savepoints.md, line 389 at r9 (raw file):

Previously, andreimatei (Andrei Matei) wrote…

the "read-only so far" doesn't seem to jibe with "rewind KV writes"

Woops, fixed.


docs/RFCS/20191014_savepoints.md, line 408 at r9 (raw file):

"Certain KV errors"? Not all the non-retriable ones?

Added a sentence to clarify.

But now I'm thinking that there's also ambiguous errors coming from a commit to worry about. Or is the plan for those to dissallow rolling back to a savepoint after attempting a COMMIT sql statement in general?

That's nothing to worry about. After a client issues the "COMMIT" statement, it's not valid to issue anything related to the SQL txn any more, including a rollback.

You may be thinking about ambiguous errors coming from a RELEASE SAVEPOINT cockroach_restart, which performs a KV commit but leaves the SQL txn open. Today we abort the SQL txn in that case and it's not recoverable. In this RFC this remains the case because we do not allow cockroach_restart to be nested under a regular savepoint.

@knz
Copy link
Contributor Author

knz commented Mar 17, 2020

I have made final adjustments to the RFC to reflect the actual implementation.

The main change is the exclusion of DDL rollbacks in the guide-level explanation.
However I also added a more complete note about:

  1. the interaction between regular savepoints and restart savepoints. @rmloveland this is for you (see section "Relationship with client-side retries")

  2. I added a section on row locks, after the discussion on sql: ROLLBACK TO SAVEPOINT does not release locks #46075

I plan to merge this PR soon and thereby close the RFC discussion. Please phrase remaining comments/concerns ASAP.

@knz knz changed the title rfcs: draft on SQL savepoints rfcs: SQL savepoints Mar 17, 2020
@knz knz force-pushed the 20191014-rfc-savepoints branch 2 times, most recently from 433ff20 to ca1e30f Compare March 17, 2020 18:01
@knz
Copy link
Contributor Author

knz commented Mar 17, 2020

@andreimatei please complete the review of the RFC and let me know if/when this can merge.

@knz knz force-pushed the 20191014-rfc-savepoints branch 2 times, most recently from 6e28429 to 8f57af1 Compare March 18, 2020 18:17
@knz
Copy link
Contributor Author

knz commented Mar 18, 2020

updated the text as suggested. RFAL

@andreimatei
Copy link
Contributor

andreimatei commented Mar 18, 2020 via email

@knz knz dismissed andreimatei’s stale review March 19, 2020 12:37

andrei says "LGTM" in comment

@knz
Copy link
Contributor Author

knz commented Mar 19, 2020

bors r+

@craig
Copy link
Contributor

craig bot commented Mar 19, 2020

Build failed

Release justification: doc only change

Release note: None
@knz
Copy link
Contributor Author

knz commented Mar 19, 2020

bors r+

@craig
Copy link
Contributor

craig bot commented Mar 19, 2020

Build succeeded

@craig craig bot merged commit 7303b7f into cockroachdb:master Mar 19, 2020
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.

sql: ROLLBACK TO SAVEPOINT does not release locks
8 participants