-
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
Add (and test) explicit support for PgBouncer #67
Comments
How would |
@abonander My hope is we can identify that it's PgBouncer on start-up. If not we'll need to tinker and provide configuration for people to use. Perhaps a way to disable the prepared cache in the database url. |
Any news on this? I would love to be able to use pgbouncer for my SQLX apps |
We'd gladly accept a pull request that improves compatibility, but otherwise it's not currently a priority. |
You should be able to get support by turning off the prepared statement cache. Set the cache capacity to 0. See https://docs.rs/sqlx/0.5.5/sqlx/postgres/struct.PgConnectOptions.html#method.statement_cache_capacity I haven't tried it but from the OP of this issue, it sounds like this should work. |
I can confirm that it does indeed work with the cache capacity set to 0. Specifically, using PgBouncer's transaction pooling mode and statement cache capacity at 0, I was able to use sqlx with AWS Lambda to begin and commit transactions. |
I don't think setting the cache capacity to 0 works in all cases. If you run queries w/o any transaction and the cache size is 0, SQLx will still prepare the statement if the query has any arguments: sqlx/sqlx-core/src/postgres/connection/executor.rs Lines 209 to 214 in 32f1273
sqlx/sqlx-core/src/postgres/connection/executor.rs Lines 177 to 179 in dd27aa0
Since pgbouncer doesn't keep the "prepare" step and the execution together, this will lead to confusing error messages where prepared statements cannot be found. I'm wondering if there is a way to pass arguments to a query w/o relying on "prepare statement" (and w/o having the user to do manual but safe string/parameter escaping). |
I don't really think that's something that SQLx should tackle. I think that could be built as a generic SQL interpolation library. If you have access to PgBouncer's config, it looks like you can set the pooling mode to Session which should make everything work as expected. Kinda defeats the point of PgBouncer, I guess, but it would work. |
Hi, I got the same issue with the error |
@uthng more discussion here: #1740 (comment) |
Add my work-around here, albeit it will bottleneck on a single connection: |
Another approach would be to implement proper prepared statement support in pgbouncer since sqlx isn't the only client suffering from this limitation, see pgbouncer/pgbouncer#695 |
Just wanted to mention that I've had that exact issue with AWS RDS Proxy (in front of RDS Postgres), and the workaround from #67 (comment) worked. I couldn't find any info on wether they use |
I have been looking into this problem and my conclusions are the following: Using pgbouncer in
In the case of problem 1), if we are using named statements and our physical connection changes, the statement will no longer be there when we try to reuse it. Even worse, some other application will have it in their connection and they could get the famous Problem 2) is much more tricky. Assuming that we solved problem 1) and we are no longer caching statements we still have the problem that currently sqlx does the following when executing queries:
The problem is that every time that we do a SYNC (see asterisks in previous list), potentially pgbouncer changes our connection and we lose our prepared statement (anonymous or not), making the binding and execution fail. Note that we can send PREPARE DESCRIBE BIND EXECUTE SYNC together, in one round-trip, but that does not help, because we need the extended type info from steps 5 and 6 before we return the first row. Assuming that all the parameters are known before we prepare the statement, step 5 can be done together with step 1, but step 6 still requires the output from step 3, so that one cannot be moved. It's also not possible to defer the requests to get the extended type info until after we do EXECUTE SYNC, because we are streaming the rows and the first row already needs that metadata available. Possible solutions that come to my mind: I'm by far not an expert in this codebase, so I may have gotten things wrong. What do you thing @abonander ? |
It seems that pgcat (a pgbouncer) alternative has just added support for prepared statements. See it here https://postgresml.org/blog/making-postgres-30-percent-faster-in-production |
Hm so pgbouncer/pgbouncer#845 in theory works. But on testing I encounterd that sqlx fails to query with Specifically, it is happening in this query:
I am not sure which side is buggy or not complete here but I thought it is worth mentioning so it isn't forgotten in the future. Since it matters it is tested with Edit: This was a bug in the pgbouncer PR and is fixed now it seems :) |
To anyone still experiencing this issue where the database is hosted in Supabase please note the following comment: |
Notable differences
Prepared statements are invalid after a
SYNC
(so they can be used but may not be cached).Apparently does not support the startup parameter
IntervalStyle
. That may need to be deferred to aSET
after connect.The text was updated successfully, but these errors were encountered: