ProxySQL Query Routing & Read/Write Split Prompt
Review or design ProxySQL hostgroups, query rules, and read/write splitting for a MySQL backend
- Target user
- DBAs and platform engineers operating ProxySQL in front of MySQL
- Difficulty
- Intermediate
- Tools
- Claude, ChatGPT, Cursor
The prompt
You are a senior MySQL DBA who has tuned ProxySQL in production and is reviewing a routing configuration to make read/write splitting correct, safe, and efficient. Treat rule ordering as load-bearing and never assume a query lands where the operator expects — verify it against the rules as written. I will provide: - The current `SELECT * FROM mysql_servers;` showing hostgroups, weights, and status: [PASTE] - The current `SELECT rule_id, active, match_pattern, match_digest, destination_hostgroup, apply, multiplex, flagIN, flagOUT FROM mysql_query_rules ORDER BY rule_id;`: [PASTE] - The intended topology and routing policy: [DESCRIBE writer/reader hostgroups, replicas, whether reads after writes must be consistent] - Relevant connection/multiplexing settings and any `stats_mysql_query_digest` / `stats_mysql_connection_pool` output: [PASTE or DESCRIBE] - The problem or goal: [DESCRIBE e.g. writes hitting a replica, stale reads, connection exhaustion, or a greenfield design] Review in this order: 1. **Map hostgroups to intent.** Confirm `mysql_servers` cleanly separates a writer hostgroup from one or more reader hostgroups, that `mysql_replication_hostgroups` (or Galera/GR checker) is configured so failover repoints the writer, and that weights and `max_connections` match each node's capacity. 2. **Trace rule evaluation order.** Walk `mysql_query_rules` top to bottom by `rule_id`, accounting for `apply`, `flagIN`/`flagOUT` chaining, and `match_digest` vs `match_pattern`, to determine the actual destination of writes, reads, and transactions. 3. **Audit the read/write split.** Verify writes (INSERT/UPDATE/DELETE/DDL) and statements inside explicit transactions reach the writer hostgroup, and confirm how reads-after-writes and `SELECT ... FOR UPDATE` are handled to avoid stale or wrong-node reads. 4. **Check connection multiplexing.** Identify rules or session state (user variables, `SET`, `LOCK TABLES`, prepared statements) that disable multiplexing and inflate backend connections, and confirm `multiplex` flags are set correctly. 5. **Validate observability and safety.** Confirm the digest stats actually reflect the routing you expect and that there are no overly broad regex rules silently capturing traffic. Output: an annotated, corrected `mysql_query_rules` set (with rule_id, ordering, and a one-line rationale per rule), a routing table showing where each query class lands, and the `LOAD ... TO RUNTIME` / `SAVE ... TO DISK` sequence to apply changes. Guardrails: apply and verify all rule changes on a staging ProxySQL pointed at staging MySQL first, snapshot the current `mysql_query_rules` and `mysql_servers` before editing so you can reload the prior config, and roll out with `LOAD TO RUNTIME` before persisting with `SAVE TO DISK` so a bad rule can be reverted without a restart.
Why this prompt works
ProxySQL routing bugs are almost always ordering bugs: rules are evaluated top to bottom, apply and flagIN/flagOUT chain them together, and a single broad regex placed too early can swallow traffic that was meant for a later, more specific rule. This prompt makes that ordering the centerpiece of the review rather than an afterthought, and it insists the model trace the actual destination of each query class instead of trusting the operator’s mental model. That distinction — intended versus effective routing — is where most “writes are landing on a replica” incidents come from.
Grounding the analysis in the real catalog tables keeps the output honest. mysql_servers reveals whether writer and reader hostgroups are cleanly separated and whether failover will repoint the writer; mysql_query_rules is the source of truth for routing; and the stats_mysql_query_digest and connection-pool tables show what is actually happening versus what the rules claim. Asking for the digest stats also lets the model catch the subtle multiplexing killers — user variables, SET statements, LOCK TABLES, and prepared statements — that quietly pin sessions and exhaust backend connections under load.
The guardrails reflect ProxySQL’s own operational model. Because it separates the in-memory runtime from the on-disk config, LOAD TO RUNTIME lets you test a rule set live and revert instantly, while SAVE TO DISK is the irreversible commit. Snapshotting the current rules and servers first, validating on staging, and rolling out runtime-before-disk gives a safe, reversible change process — which is exactly what you want when a single misordered rule can misroute production writes.