Skip to content

fix: mirror prepared statement mode in session pooling#827

Merged
levkk merged 4 commits intopgdogdev:mainfrom
costi:bug/mirror_prepared_statements
Mar 13, 2026
Merged

fix: mirror prepared statement mode in session pooling#827
levkk merged 4 commits intopgdogdev:mainfrom
costi:bug/mirror_prepared_statements

Conversation

@costi
Copy link
Contributor

@costi costi commented Mar 13, 2026

This might be a two bug layer. First, it's might be an issue with DEALLOCATE sent as a simple query that doesn't get rewritten, which causes a transaction failure and messes up the whole mirroring.

But I'm using pgdog in session mode with mirroring to test performance to see if I can switch the database to a cheaper one so I'm not affected by the DEALLOCATE bug on the source. What I noticed is that the mirror traffic gets this error:

ERROR:  prepared statement "pdo_stmt_00000001" does not exist
STATEMENT:  DEALLOCATE pdo_stmt_00000001

I also included a fix to speed up the dockerfile build with caches since I iterated on the dockerfile with the fix.
I also have a repro with a docker-compose and a simple php app here: https://github.com/costi/pgdog-pdo-repro

The flow is like this:

  1. In session mode, the client path uses the effective prepared-statements setting from:
config.prepared_statements()
  1. ConfigAndUsers::prepared_statements() disables prepared statements in session mode:
pub fn prepared_statements(&self) -> PreparedStatements {
    if self.config.general.pooler_mode == PoolerMode::Session {
        PreparedStatements::Disabled
    } else {
        self.config.general.prepared_statements
    }
}
  1. The mirror path was not using that effective value. It constructed its prepared-statement state with the raw default/configured level instead.

  2. So with:

pooler_mode = "session"
prepared_statements = "extended"

the source/client path effectively ran with Disabled, while the mirror path still ran with Extended.

  1. That caused the mirror path to rewrite extended-protocol prepared statement names to __pgdog_*, while the source path kept the original PDO names like pdo_stmt_00000001.

  2. Later, PDO sent simple SQL cleanup:

DEALLOCATE pdo_stmt_00000001
  1. The mirror backend only knew the prepared statement under the rewritten __pgdog_* name, so PostgreSQL correctly errored:
ERROR:  prepared statement "pdo_stmt_00000001" does not exist
STATEMENT:  DEALLOCATE pdo_stmt_00000001

@CLAassistant
Copy link

CLAassistant commented Mar 13, 2026

CLA assistant check
All committers have signed the CLA.

@codecov
Copy link

codecov bot commented Mar 13, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@levkk
Copy link
Collaborator

levkk commented Mar 13, 2026

Nice find. I knew we should of added php tests :) It's even in the repo, just not running in CI. Could you just run cargo fmt and it should be good to go. The dockerfile changes seem good to me, I just don't fully understand them. Do they change how the image is build in GitHub? We want to be sure its a fresh build every time. We don't generally use docker for development and that specific file is for production deployments. Do you think it would be simpler to have a separate one for development where you can add pretty much anything else needed for local dev?

@costi
Copy link
Contributor Author

costi commented Mar 13, 2026

Removed the Dockerfile changes. Fixed the fmt.
Do you want me to add php integration tests?

@levkk
Copy link
Collaborator

levkk commented Mar 13, 2026

Do you want me to add php integration tests?

That would be amazing, if you have a moment. We have php somewhere in the repo already (I think Laravel), feel free to delete that, it's not used.

@costi
Copy link
Contributor Author

costi commented Mar 13, 2026

Added a php mirror test and fixed and enabled the ruby mirror test which was not enabled in CI.
The php mirror test fails with pgdog master and passes with the pgdog from this branch.

@levkk levkk changed the title Fix mirror prepared statement mode in session pooling fix: mirror prepared statement mode in session pooling Mar 13, 2026
@levkk
Copy link
Collaborator

levkk commented Mar 13, 2026

Very cool. Thank you!

@levkk levkk merged commit bce0e7a into pgdogdev:main Mar 13, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants