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

[release/6.0-rc1] Fix #25225 by forcing usage of renting and populating commands when using relational command cache #25668

Merged
merged 3 commits into from
Aug 24, 2021

Conversation

billybraga
Copy link
Contributor

@billybraga billybraga commented Aug 23, 2021

Fixes #25225.

Description

As part of the query performance work in EF Core 6.0, a concurrency state bug was accidentally introduced where the same stateful object (RelationalCommand) may get reused concurrently, leading to issues.

Customer Impact

Running the same query concurrently as a split query on SQL Server may fail in unpredictable ways.

How found

User report.

Test coverage

Included in this PR.

Regression?
Yes, as result of a performance optimization introduced in EF Core 6.0.

Risk

Very low, the PR simply duplicates the stateful RelationalCommand for the non-primary split query case, a technique already used in other scenarios (e.g. single query).

There is also a remaining possible issue that I see: RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.PopulateSplitIncludeCollection(...) (and PopulateSplitIncludeCollectionAsync) don't return their command template using Connection.ReturnCommand(...) like the other places where commands are rented.

Billy Braga added 2 commits August 20, 2021 12:06
…te split collection (only use cached command as template)
@dnfadmin
Copy link

dnfadmin commented Aug 23, 2021

CLA assistant check
All CLA requirements met.

@billybraga billybraga changed the title Force usage of renting and populating commands when using relational command cache Fix #25225 by forcing usage of renting and populating commands when using relational command cache Aug 23, 2021
Copy link
Member

@roji roji left a comment

Choose a reason for hiding this comment

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

This looks good to me, thanks @billybraga. We'll discuss later today about whether this can go into rc1.

src/EFCore.Relational/Storage/IRelationalCommand.cs Outdated Show resolved Hide resolved
@roji roji linked an issue Aug 24, 2021 that may be closed by this pull request
Co-authored-by: Shay Rojansky <roji@roji.org>
@roji
Copy link
Member

roji commented Aug 24, 2021

There is also a remaining possible issue that I see: RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.PopulateSplitIncludeCollection(...) (and PopulateSplitIncludeCollectionAsync) don't return their command template using Connection.ReturnCommand(...) like the other places where commands are rented.

Yeah, that was partially intentional; right now the command renting mechanism on RelationalConnection only "pools" one relational command. When using split query (on SQL Server), multiple relational commands are used in parallel, which means they wouldn't be cached anyway - only the main one would (FWIW this was also the original logic behind renting and populating for the main command but not for the others, which led to this bug).

In any case, not returning a command to the connection isn't a bug - it's just a missed optimization at most; we can always improve this and implement a real pool with more than one commands for SQL Server. In any case I suggest we keep this separate from this bug, which is important to fix ASAP - I'll open a tracking issue for the rest.

@smitpatel smitpatel self-requested a review August 24, 2021 15:11
@ajcvickers ajcvickers changed the title Fix #25225 by forcing usage of renting and populating commands when using relational command cache [release/6.0-rc1] Fix #25225 by forcing usage of renting and populating commands when using relational command cache Aug 24, 2021
@ajcvickers ajcvickers added this to the 6.0.0-rc1 milestone Aug 24, 2021
@ajcvickers ajcvickers changed the base branch from main to release/6.0-rc1 August 24, 2021 16:13
@ajcvickers ajcvickers changed the base branch from release/6.0-rc1 to main August 24, 2021 16:14
@ajcvickers
Copy link
Member

Merging this into main now, will port fix to release branches.

@ajcvickers ajcvickers merged commit bbcb3a6 into dotnet:main Aug 24, 2021
@billybraga billybraga deleted the issue25225 branch August 24, 2021 18:02
ajcvickers pushed a commit that referenced this pull request Aug 24, 2021
…ng commands when using relational command cache (#25668)

* Fix #25225 by avoiding reusing the relational command to populate split collection (only use cached command as template)

* Extract the cached part of IRelationalCommand into IRelationalCommandTemplate to avoid confusion.

* Apply suggestions from code review

Co-authored-by: Shay Rojansky <roji@roji.org>

Co-authored-by: Billy Braga <bbraga@progi.com>
Co-authored-by: Shay Rojansky <roji@roji.org>
@ajcvickers ajcvickers removed this from the 6.0.0-rc1 milestone Oct 6, 2021
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.

Concurrency state issues with split query
5 participants