-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Postgres: fetch_one/fetch_optional doesn't close opened server side cursor #2077
Comments
fetch_one and fetch_optional can close the portal explicitly by issuing a Close command after Sync in the same pipelined batch. The sqlx documention for |
The unclosed portal affects Postgres too. I found a discussion that shows the deadlock reproduced by the following test code. In this test session c3 leaves the unnamed portal opened. 'VACUUM FREEZE' command in the concurrent session blocks:
The third session can't commit:
The discussion resulted in adding a Close command to libpq to PQsendQuery in pipeline mode. Actually the Close command is issued after Execute and before Sync. The first reply from the discussion:
|
There is a fix in the CockroachDB repo that implements unnamed portal drop behavior for Bind messages. |
I'd accept a PR to include the |
@abonander , I've made the PR |
Closed by #2081 |
Bug Description
Current implementation of fetch_one/fetch_optional for Postgres doesn't close the used database resource - the server side cursor.
It just waits for the expected single data row (for fetch_optional it's the case when query returns one row) and relies on multiple workarounds across the codebase that will handle
PortalSuspended
message. I copied one of the workarounds when I recently implemented the pipelined query execution feature.The open unnamed cursor is problematic in CockroachDB because it doesn't support multiple database cursors and rejects the next query.
When I run the provided below snippet of async code against CockroachDB I get the following error:
Expected behavior
fetch_one/fetch_optional should close the server side cursor it uses.
The implementation adds
Close
command to the pipeline -Bind
,Execute
,Close
andSync
and waits for PortalSuspended and CloseComplete messages.With this implementation it's possible to remove multiple workarounds across the code base that handle PortalSuspended message.
A piece of Postgres documentation for Close command:
Another option could be an alternative offetch_one/fetch_optional
(maybefetch_all_return_one
?) that fetches all results then does client side filtering and returns the first data row (or optional row). This option will require less database round trips and will not use protocol level result set limit but may waste more resources if the query actually returns more than one row.Minimal Reproduction
Related issues
There are multiple related issues with discussions or implemented workarounds:
PortalSuspended
when binding domain type of composite type of domain type #1110Info
rustc --version
: [rustc 1.63.0 (4b91a6ea7 2022-08-08)]The text was updated successfully, but these errors were encountered: