-
Notifications
You must be signed in to change notification settings - Fork 876
Reset connection when closing within TransactionScope #6424
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2619,8 +2619,14 @@ void Cleanup() | |
| _certificates = null; | ||
| } | ||
|
|
||
| [MemberNotNull(nameof(_resetWithoutDeallocateMessage))] | ||
| void GenerateResetMessage() | ||
| { | ||
| // Generate a reset message that resets connection state without using DISCARD ALL. | ||
| // This is used in two scenarios: | ||
| // 1. When closing a pooled connection that has prepared statements (DISCARD ALL would deallocate them) | ||
| // 2. When closing a connection within an enlisted System.Transactions transaction (DISCARD ALL cannot | ||
| // run inside a transaction block, but its component commands can) | ||
roji marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| var sb = new StringBuilder("SET SESSION AUTHORIZATION DEFAULT;RESET ALL;"); | ||
| _resetWithoutDeallocateResponseCount = 2; | ||
| if (DatabaseInfo.SupportsCloseAll) | ||
|
|
@@ -2728,6 +2734,29 @@ internal async Task Reset(bool async) | |
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Called when a pooled connection with an enlisted System.Transactions transaction is closed. | ||
| /// Since we're inside a transaction block, we cannot send DISCARD ALL, DISCARD TEMP or DISCARD SEQUENCES; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment says This seems to contradict the comment, or am I missing something?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The comment is wrong (AI-generated), I'll fix - DISCARD TEMP and DISCARD SEQUENCES seem to work fine within transactions (but DISCARD ALL is indeed disallowed).
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I imagine that's to make sure that in case they add a new command in the future which can't run in transactions, that way they'll not break anyone. |
||
| /// we prepend a reset message that only includes commands that can safely run within a transaction. | ||
| /// </summary> | ||
| internal void ResetWithinEnlistedTransaction() | ||
| { | ||
| // Our buffer may contain unsent prepended messages, so clear it out. | ||
| WriteBuffer.Clear(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we start user action here to prevent messing up concurrent keepalive? |
||
| PendingPrependedResponses = 0; | ||
|
|
||
| ResetReadBuffer(); | ||
|
|
||
| if (_resetWithoutDeallocateMessage is null) | ||
| { | ||
| GenerateResetMessage(); | ||
| } | ||
roji marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| PrependInternalMessage(_resetWithoutDeallocateMessage, _resetWithoutDeallocateResponseCount); | ||
|
|
||
| DataReader.UnbindIfNecessary(); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// The connector may have allocated an oversize read buffer, to hold big rows in non-sequential reading. | ||
| /// This switches us back to the original one and returns the buffer to <see cref="ArrayPool{T}" />. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@roji do you think it might make sense to move
_resetWithoutDeallocateMessageto the data source/database info, rather than cache per each connector? Not in this pr of course.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice idea, makes sense.