Skip to content

sql: support FOR {UPDATE,SHARE} NOWAIT#52522

Merged
craig[bot] merged 1 commit intocockroachdb:masterfrom
nvb:nvanbenschoten/noWait
Aug 18, 2020
Merged

sql: support FOR {UPDATE,SHARE} NOWAIT#52522
craig[bot] merged 1 commit intocockroachdb:masterfrom
nvb:nvanbenschoten/noWait

Conversation

@nvb
Copy link
Copy Markdown
Contributor

@nvb nvb commented Aug 7, 2020

Fixes half of #40476.

In #52388, we added support for a new Error wait policy to be attached
to BatchRequests. This wait policy dictates that if a request encounters
a conflicting locks held by another active transaction, it should raise
an error instead of blocking.

These semantics closely match those of FOR {UPDATE,SHARE} NOWAIT in
PostgreSQL. With NOWAIT, the statement reports an error, rather than
waiting, if a selected row cannot be locked immediately. This means that
we are able to use the new kv-level wait policy to implement NOWAIT in
SQL. Doing so is fairly mechanical, as a lot of the plumbing necessary
was already put into place in #44429.

The only difference I can see in the semantics is that in PostgreSQL,
rows that are being INSERTed by one transaction are not even considered
for locking by other transactions, so NOWAIT will not throw an error
when encountering these rows. Instead, it will silently ignore them.
This has less to do with NOWAIT itself, and more to do with a difference
in the concurrency control implementation between Cockroach and
PostgreSQL. Since this isn't specific to NOWAIT, I don't think it's a
blocker for this change.

Release note (sql change): SELECT ... FOR {UPDATE,SHARE} NOWAIT is now
supported. The option can be used to throw and error instead of blocking
on contended row-level lock acquisition.

@nvb nvb requested review from a team, andreimatei and jordanlewis August 7, 2020 21:08
@nvb nvb requested a review from a team as a code owner August 7, 2020 21:08
@nvb nvb requested review from dt and removed request for a team and dt August 7, 2020 21:08
@cockroach-teamcity
Copy link
Copy Markdown
Member

This change is Reviewable

@nvb nvb force-pushed the nvanbenschoten/noWait branch from 62ba834 to 89f5781 Compare August 8, 2020 00:34
Copy link
Copy Markdown
Member

@jordanlewis jordanlewis left a comment

Choose a reason for hiding this comment

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

Wow, this was surprisingly simple - most of the "meat" of the change happens somewhere in KV. Amazing!

How much more work is SKIPLOCKED? I'm guessing a lot? That one would be really useful for queue workloads.

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


pkg/sql/row/errors.go, line 172 at r2 (raw file):

		var relation string
		if desc, ok := descForKey.KeyToDesc(wiErr.Intents[0].Key); ok {
			relation = fmt.Sprintf("relation %q", desc.Name)

I think we like to use the table@index form a lot and might be nice here, if we have enough information. Maybe we don't? But in general, the more information we can extract here the better, I think... unless you were just copying the Postgres message.


pkg/sql/row/errors.go, line 174 at r2 (raw file):

			relation = fmt.Sprintf("relation %q", desc.Name)
		} else {
			relation = "interleaved relation"

can't wait to never have to see stuff like this ever again!

@nvb nvb force-pushed the nvanbenschoten/noWait branch from 89f5781 to 0144b6a Compare August 8, 2020 01:36
Copy link
Copy Markdown
Contributor Author

@nvb nvb left a comment

Choose a reason for hiding this comment

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

How much more work is SKIPLOCKED? I'm guessing a lot? That one would be really useful for queue workloads.

Yeah, SKIP LOCKED will be significantly more work. Instead of just throwing an error when we detect that the owner of a conflicting lock is still active, we'd instead need to coordinate with the storage layer to ignore the value that is locked. This actually becomes feasible once the iterators that we use at the MVCC layer start capturing lock-table state (part of #41720), but it's still tricky.

SKIP LOCKED is also deliberately returning an inconsistent view of the table's data, but still with very specific semantics, so it's a little more questionable whether it's something we want to implement in the first place.

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


pkg/sql/row/errors.go, line 172 at r2 (raw file):

Previously, jordanlewis (Jordan Lewis) wrote…

I think we like to use the table@index form a lot and might be nice here, if we have enough information. Maybe we don't? But in general, the more information we can extract here the better, I think... unless you were just copying the Postgres message.

This was just copying the Postgres message word for word.


pkg/sql/row/errors.go, line 174 at r2 (raw file):

Previously, jordanlewis (Jordan Lewis) wrote…

can't wait to never have to see stuff like this ever again!

😃

@jordanlewis
Copy link
Copy Markdown
Member

This was just copying the Postgres message word for word.

We're not bound to the Postgres error messages necessarily. We like to copy them because often they're better than what we come up with. That being said, in this circumstance, can't we do significantly better? One of the biggest complaints customers tend to have about our transaction model is that they don't understand what conflicts are caused by when they get error messages. Can we do better in this circumstance? I'd love to see, if it were possible, the conflicting row, index and table.

Overall this change LGTM though! Happy to see this go in.

@nvb
Copy link
Copy Markdown
Contributor Author

nvb commented Aug 10, 2020

We're not bound to the Postgres error messages necessarily. We like to copy them because often they're better than what we come up with. That being said, in this circumstance, can't we do significantly better? One of the biggest complaints customers tend to have about our transaction model is that they don't understand what conflicts are caused by when they get error messages. Can we do better in this circumstance? I'd love to see, if it were possible, the conflicting row, index and table.

All fair points. We have the full key here, so we should be able to return as much information as we do with unique constraint violations. I'll try that out later this week and see how it goes.

Thanks again for the review.

@nvb nvb force-pushed the nvanbenschoten/noWait branch from 0144b6a to bdb0514 Compare August 16, 2020 04:10
@nvb
Copy link
Copy Markdown
Contributor Author

nvb commented Aug 16, 2020

I'll try that out later this week and see how it goes.

Done. I think this turned out nicely. PTAL when you get a chance.

Fixes half of cockroachdb#40476.

In cockroachdb#52388, we added support for a new `Error` wait policy to be attached
to BatchRequests. This wait policy dictates that if a request encounters
a conflicting locks held by another active transaction, it should raise
an error instead of blocking.

These semantics closely match those of FOR {UPDATE,SHARE} NOWAIT in
PostgreSQL. With NOWAIT, the statement reports an error, rather than
waiting, if a selected row cannot be locked immediately. This means that
we are able to use the new kv-level wait policy to implement NOWAIT in
SQL. Doing so is fairly mechanical, as a lot of the plumbing necessary
was already put into place in cockroachdb#44429.

The only difference I can see in the semantics is that in PostgreSQL,
rows that are being INSERTed by one transaction are not even considered
for locking by other transactions, so NOWAIT will not throw an error
when encountering these rows. Instead, it will silently ignore them.
This has less to do with NOWAIT itself, and more to do with a difference
in the concurrency control implementation between Cockroach and
PostgreSQL. Since this isn't specific to NOWAIT, I don't think it's a
blocker for this change.

Release note (sql change): SELECT ... FOR {UPDATE,SHARE} NOWAIT is now
supported. The option can be used to throw and error instead of blocking
on contended row-level lock acquisition.
@nvb nvb force-pushed the nvanbenschoten/noWait branch from bdb0514 to 7aed72c Compare August 16, 2020 04:40
@nvb
Copy link
Copy Markdown
Contributor Author

nvb commented Aug 18, 2020

bors r+

@craig
Copy link
Copy Markdown
Contributor

craig bot commented Aug 18, 2020

Build succeeded:

@craig craig bot merged commit d1afb84 into cockroachdb:master Aug 18, 2020
@nvb nvb deleted the nvanbenschoten/noWait branch August 19, 2020 03:32
@nvb nvb added the docs-todo label Sep 10, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants