When ProxySQL reports zero ONLINE backends in a hostgroup, every query routed to that hostgroup fails immediately. If the affected hostgroup handles writes, all INSERT, UPDATE, and DELETE operations fail. If it is a reader hostgroup, read queries either error out or, depending on query rules, flood a writer hostgroup not sized for that load.
Clients see the error “Hostgroup X has no servers available!” or generic connection timeouts. Application error rates spike. Questions drops toward zero while Client_Connections_aborted rises.
This is a PAGE-level condition, but only under gating criteria that exclude false positives. The diagnostic path: confirm the outage is real (not cold start or idle), determine whether backends are reachable, then inspect monitor check results to identify the specific failure mode.
What this means
ProxySQL tracks four backend states per hostgroup: ONLINE, SHUNNED, OFFLINE_SOFT, and OFFLINE_HARD. Zero ONLINE means every backend in the hostgroup is in one of the three degraded states. No queries can be served for that traffic class.
Gate the PAGE condition with three requirements:
- Zero ONLINE backends sustained for more than 2 monitor intervals. With the default
mysql-monitor_ping_intervalof 8000ms, this is approximately 16 seconds. ProxySQL_Uptime > 600to exclude cold starts where pools are empty and the monitor has not completed a full check cycle.Client_Connections_non_idle > 0ORQuestionsrate > 0 to exclude idle instances with no real traffic.
Without these gates, the alert fires on cold starts, idle standalone instances, and reader hostgroups that legitimately SHUN all lagging replicas during backup windows. With them, you have a confirmed service outage requiring immediate investigation.
The backends can be non-ONLINE for different reasons, each requiring a different fix. The critical first step: determine whether the backends are actually unreachable or whether ProxySQL’s own monitoring and shun logic removed them from rotation.
flowchart TD
A["Zero ONLINE backends
in a hostgroup"] --> B{"Backends reachable
directly?"}
B -- "No" --> C["Network partition or
backend MySQL down"]
B -- "Yes" --> D{"Monitor checks
failing?"}
D -- "Yes" --> E["Identify check type:
connect, ping, or lag"]
D -- "No" --> F{"Config problem?
Check weight, drift,
Galera shunned_automatic"}
E --> G["Connection errors: check
max_connect_errors, credentials"]
E --> H["Lag: check replication
on all backends"]
F --> I["Fix config and
LOAD TO RUNTIME"]Common causes
| Cause | What it looks like | First thing to check |
|---|---|---|
| All backends unreachable | Monitor connect/ping checks all ERR, ConnERR rising on every backend, Latency_us at 0 | Connect directly to a backend, bypassing ProxySQL |
| All backends SHUNNED from connection errors | ConnERR high, status SHUNNED across the hostgroup | Check if MySQL blocked the ProxySQL host via max_connect_errors |
| All backends SHUNNED from replication lag | MySQL_Monitor_replication_lag_check_ERR rising, all replicas exceed max_replication_lag | Check Seconds_Behind_Master directly on each replica |
| Monitor credentials expired | All monitor checks ERR, data-plane connections may still work briefly until pool drains | Verify mysql-monitor_username and mysql-monitor_password against backend grants |
| Configuration drift | mysql_servers has entries, runtime_mysql_servers shows wrong hostgroup or missing servers | Compare mysql_servers against runtime_mysql_servers |
| Galera max_writers issue | Writer hostgroup all SHUNNED | Check if mysql_galera_hostgroups.max_writers is configured |
| weight=0 on all servers | Servers ONLINE in runtime_mysql_servers but never receive traffic (not a zero-ONLINE condition, but mimics the symptoms) | Check weight column values |
Quick checks
All commands query the ProxySQL admin interface (port 6032) and are read-only. Safe to run during an active incident.
# Check backend status and connection pool per hostgroup
mysql -u admin -padmin -h 127.0.0.1 -P 6032 \
-e "SELECT hostgroup, srv_host, srv_port, status, ConnUsed, ConnFree, ConnOK, ConnERR FROM stats_mysql_connection_pool;"
# Check runtime server configuration (weight, max_connections, status)
mysql -u admin -padmin -h 127.0.0.1 -P 6032 \
-e "SELECT hostgroup_id, hostname, port, status, weight, max_connections FROM runtime_mysql_servers;"
# Check monitor check success/failure counts
mysql -u admin -padmin -h 127.0.0.1 -P 6032 \
-e "SELECT Variable_Name, Variable_Value FROM stats_mysql_global WHERE Variable_Name LIKE 'MySQL_Monitor_%';"
# Verify alert gating conditions
mysql -u admin -padmin -h 127.0.0.1 -P 6032 \
-e "SELECT Variable_Name, Variable_Value FROM stats_mysql_global WHERE Variable_Name IN ('ProxySQL_Uptime', 'Client_Connections_non_idle', 'Questions');"
# Check recent monitor ping log entries for failure patterns
mysql -u admin -padmin -h 127.0.0.1 -P 6032 \
-e "SELECT * FROM monitor.mysql_server_ping_log ORDER BY time_start_us DESC LIMIT 30;"
# Check monitor workers are alive (zero means monitoring is disabled)
mysql -u admin -padmin -h 127.0.0.1 -P 6032 \
-e "SELECT Variable_Name, Variable_Value FROM stats_mysql_global WHERE Variable_Name IN ('MySQL_Monitor_Workers', 'MySQL_Monitor_Workers_Aux');"
# Direct backend connectivity check (bypass ProxySQL entirely)
mysql -u <backend_user> -p -h <backend_host> -P <backend_port> \
-e "SELECT @@hostname, @@read_only;"
# Check per-errno error breakdown (ProxySQL 2.x+)
mysql -u admin -padmin -h 127.0.0.1 -P 6032 \
-e "SELECT * FROM stats_mysql_errors ORDER BY last_seen DESC LIMIT 20;"
How to diagnose it
Confirm the outage is real. Check
ProxySQL_Uptime,Client_Connections_non_idle, andQuestionsrate. If uptime is under 600, this may be a cold start. If non_idle and Questions are both zero, the instance is idle and the zero-ONLINE state may be expected. The outage is real when uptime > 600 and there is active traffic with zero ONLINE backends.Verify backends are reachable directly. Connect to at least one backend MySQL instance from the ProxySQL host, bypassing the proxy. If the direct connection fails, the problem is network, firewall, DNS, or the backend MySQL process itself. Check security groups, firewall rules, and DNS resolution. If the direct connection succeeds, ProxySQL’s monitor or shun logic is the issue.
Identify the degraded state. Query
stats_mysql_connection_pooland look at thestatuscolumn for each backend. If all are SHUNNED, the backends were removed by ProxySQL’s protection mechanism, not by operator action. If all are OFFLINE_HARD, someone or something explicitly removed them. If the hostgroup has no entries inruntime_mysql_servers, the configuration is missing servers.Check monitor check results. Look at
MySQL_Monitor_connect_check_ERRandMySQL_Monitor_ping_check_ERRinstats_mysql_global. Rising error counts tell you which check type is failing. Cross-reference with the monitor log tables (monitor.mysql_server_ping_log,monitor.mysql_server_connect_log) for specific error messages. IfMySQL_Monitor_Workersis zero, the monitor module is disabled and status decisions are stale.Check for configuration problems. Compare
mysql_servers(MEMORY layer) againstruntime_mysql_servers(RUNTIME layer). If they differ, aLOAD MYSQL SERVERS TO RUNTIMEwas never executed after a change. Check theweightcolumn: weight=0 means the server is never used for routing despite appearing ONLINE. Check whether Galeramax_writersis configured.Check for backend-side blocking. If ProxySQL has been generating many failed connection attempts, MySQL’s
max_connect_errors(default 100) may have blocked the ProxySQL host. The backend returns “Host ‘X’ is blocked because of many connection errors.” This creates a death spiral: failed connections trigger shunning, shun recovery triggers more retries, more failures accumulate, and the block persists.
Metrics and signals to monitor
| Signal | Why it matters | Warning sign |
|---|---|---|
| Backend status per hostgroup | Directly indicates whether queries can be routed | Zero ONLINE in any hostgroup with active traffic |
| MySQL_Monitor_connect_check_ERR | Leading indicator of backend reachability problems | Rate increasing before status transitions |
| MySQL_Monitor_ping_check_ERR | Leading indicator of backend responsiveness problems | Rate increasing before status transitions |
| MySQL_Monitor_replication_lag_check_ERR | Indicates replicas falling behind | All replicas exceeding max_replication_lag simultaneously |
| ConnERR per backend | Failed connection attempts to backends | High rate approaching the shun threshold |
| MySQL_Monitor_Workers | Confirms monitor module is running | Zero means monitoring is disabled, status decisions are stale |
| ProxySQL_Uptime | Gates cold-start false positives | Under 600 means pools may still be warming |
| Client_Connections_non_idle | Confirms real traffic exists | Zero means idle instance, not a genuine outage |
| Questions rate | Confirms overall throughput | Drop to near-zero with rising errors confirms client impact |
| backend_offline_during_query | Queries that failed because backend went offline mid-execution | Sustained increase confirms real query failures |
Fixes
Backends genuinely unreachable
If direct connectivity to backends fails, the problem is outside ProxySQL. Fix the network path (firewall rules, security groups, DNS resolution) or restart the backend MySQL process. Once backends are reachable, ProxySQL’s monitor will detect recovery within one check interval and transition backends back to ONLINE automatically.
All backends SHUNNED from connection errors
The effective shun threshold is min(mysql-shun_on_failures, mysql-connect_retries_on_failure). With defaults of 5 and 10 respectively, the effective threshold is 5. If all backends in a hostgroup accumulate errors faster than the recovery cycle, they stay perpetually SHUNNED.
MySQL max_connect_errors blocking. If the backend has blocked the ProxySQL host, run mysqladmin flush-hosts on the affected backend to clear the block. This is disruptive to that backend’s connection state but necessary to break the death spiral. Then investigate why the errors accumulated.
Intermittent network issues. If connections succeed sometimes and fail other times, ConnERR accumulates alongside ConnOK. Run mtr or traceroute between the ProxySQL host and backend. Consider increasing mysql-shun_recovery_time_sec (default 10s) to give the network more time to recover between retry cycles.
Raising mysql-shun_on_failures alone may have no effect if mysql-connect_retries_on_failure is lower. The effective threshold is always the minimum of the two.
All backends SHUNNED from replication lag
If all replicas exceed their configured max_replication_lag, ProxySQL correctly SHUNNs them all. The fix is on the replication side: investigate why replicas cannot keep up. Common causes include large DDL operations, long-running transactions on the primary, or insufficient replica I/O capacity.
If the lag is transient (backup window, batch job), consider downgrading the PAGE to a TICKET for reader-only hostgroups where a writer hostgroup still has ONLINE backends.
Monitor credentials expired
When mysql-monitor_password no longer matches the backend grants, all monitor checks fail. ProxySQL cannot verify backend health and shuns them. Data-plane connections using credentials from mysql_users may still work briefly from the connection pool until they drain.
Fix both credential sets if needed:
# Changes runtime state.
mysql -u admin -padmin -h 127.0.0.1 -P 6032 \
-e "SET mysql-monitor_password='<new_password>'; LOAD MYSQL VARIABLES TO RUNTIME; SAVE MYSQL VARIABLES TO DISK;"
# Changes runtime state. Disconnects active user sessions on next reconnect.
mysql -u admin -padmin -h 127.0.0.1 -P 6032 \
-e "UPDATE mysql_users SET password='<new_password>' WHERE username='<user>'; LOAD MYSQL USERS TO RUNTIME; SAVE MYSQL USERS TO DISK;"
After updating, monitor check results should transition from ERR to OK within one check interval, and backends will return to ONLINE.
Configuration problems
Config drift. If mysql_servers and runtime_mysql_servers differ, load the pending changes. Verify the MEMORY configuration is correct before executing:
# Changes runtime state. Verify mysql_servers contents first.
mysql -u admin -padmin -h 127.0.0.1 -P 6032 \
-e "LOAD MYSQL SERVERS TO RUNTIME; SAVE MYSQL SERVERS TO DISK;"
weight=0. Set weight to a non-zero value for each affected server, then load to runtime. ProxySQL default weight is 1000.
Galera max_writers issue. If mysql_galera_hostgroups.max_writers is set and the writer hostgroup is all SHUNNED, ProxySQL will not promote backup writers automatically when the primary fails. The immediate workaround is to manually intervene on the SHUNNED servers or temporarily adjust max_writers.
Prevention
Track configuration layer consistency. Compare
mysql_serversvsruntime_mysql_serversvs disk state regularly. Alert on divergence sustained for more than 10 minutes. Most config drift incidents happen when an operator changes MEMORY but forgetsLOAD TO RUNTIME, or loads to RUNTIME but forgetsSAVE TO DISK.Monitor the monitor. Track
MySQL_Monitor_Workersand allMySQL_Monitor_*_check_ERRcounters. If the monitor module is disabled or failing, ProxySQL’s status decisions become stale. A zero-ONLINE condition caused by monitor failure is preventable with early detection.Watch shun and unshun cycles. Track
ConnERRrates per backend against the effective shun threshold. If error rates approach the threshold on multiple backends simultaneously, investigate before they all get shunned.Keep monitor credentials in sync. Treat
mysql-monitor_passwordchanges as a coordinated operation with backend grant updates. Credential rotation that does not update ProxySQL is one of the most common causes of silent backend shunning.Verify weight values when adding servers. Setting weight=0 silently excludes a server from routing. Validate weight values as part of server provisioning.
Set replication lag thresholds thoughtfully.
max_replication_lagshould reflect what your application can tolerate, not a value that causes all replicas to be SHUNNED simultaneously during normal operations.
How Netdata helps
Netdata’s ProxySQL collector surfaces the specific signals that distinguish a real backend outage from a cold start, idle instance, or transient shun cycle:
- Per-second backend status tracking shows exactly when each backend transitioned from ONLINE to SHUNNED or OFFLINE_HARD, and whether the transition correlates with a monitor check failure, a ConnERR spike, or a configuration change.
- Monitor check result rates (connect, ping, read_only, replication_lag OK/ERR) provide leading indicators before backends reach zero-ONLINE. A rising ERR rate across check types signals network or credential problems before the outage is total.
- ProxySQL_Uptime and Client_Connections_non_idle gating eliminates false-positive pages from cold starts and idle instances, so the alert only fires when real traffic is failing.
- ConnERR per backend correlates directly with shun events, making it clear whether backends are failing because ProxySQL cannot reach them or because MySQL blocked the ProxySQL host.
- Questions rate and Client_Connections_aborted confirm client-visible impact and distinguish “queries are failing” from “there is no traffic to this hostgroup.”






