Configure MySQL connection pooling with ProxySQL 2.6 for high availability and performance optimization

Intermediate 45 min Apr 27, 2026 176 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Set up ProxySQL 2.6 to manage MySQL connection pooling, load balancing, and automatic failover. This tutorial covers backend server configuration, health checks, query routing rules, and monitoring for production MySQL environments.

Prerequisites

  • Multiple MySQL servers (master and replicas)
  • Root or sudo access
  • Basic MySQL administration knowledge
  • Network connectivity between ProxySQL and MySQL servers

What this solves

MySQL connection pooling with ProxySQL eliminates connection overhead, manages database load distribution, and provides automatic failover when backend servers go down. ProxySQL acts as an intelligent proxy layer between your applications and MySQL servers, handling connection reuse, query routing, and health monitoring without requiring application changes.

Step-by-step installation

Update system packages

Start by updating your package manager to ensure you get the latest versions and security patches.

sudo apt update && sudo apt upgrade -y
sudo dnf update -y

Install ProxySQL 2.6

Add the official ProxySQL repository and install the latest 2.6 version. This provides the most recent features and security updates.

wget -O - 'https://repo.proxysql.com/ProxySQL/proxysql-2.6.x/repo_pub_key' | sudo apt-key add -
echo "deb https://repo.proxysql.com/ProxySQL/proxysql-2.6.x/$(lsb_release -sc)/ ./" | sudo tee /etc/apt/sources.list.d/proxysql.list
sudo apt update
sudo apt install -y proxysql2
cat > /etc/yum.repos.d/proxysql.repo << 'EOF'
[proxysql_repo]
name= ProxySQL YUM repository
baseurl=https://repo.proxysql.com/ProxySQL/proxysql-2.6.x/centos/$releasever
gpgcheck=1
gpgkey=https://repo.proxysql.com/ProxySQL/proxysql-2.6.x/repo_pub_key
EOF
sudo dnf install -y proxysql2

Create ProxySQL admin user

Create a dedicated user for ProxySQL operations. This follows security best practices by avoiding root access.

sudo groupadd proxysql
sudo useradd -r -g proxysql -s /bin/false -d /var/lib/proxysql proxysql
sudo chown -R proxysql:proxysql /var/lib/proxysql
sudo chmod 755 /var/lib/proxysql

Configure ProxySQL main settings

Set up the primary configuration file with admin interface, MySQL interface, and basic clustering settings. This configuration enables both admin access and MySQL proxy functionality.

datadir="/var/lib/proxysql"
errorlog="/var/lib/proxysql/proxysql.log"

admin_variables=
{
    admin_credentials="proxysql-admin:StrongAdminPass123!"
    mysql_ifaces="0.0.0.0:6032"
    refresh_interval=2000
    debug=false
    hash_passwords=true
}

mysql_variables=
{
    threads=4
    max_connections=2048
    default_query_delay=0
    default_query_timeout=36000000
    have_compress=true
    poll_timeout=2000
    interfaces="0.0.0.0:6033"
    default_schema="information_schema"
    stacksize=1048576
    server_version="8.0.35"
    connect_timeout_server=3000
    monitor_username="proxysql_monitor"
    monitor_password="MonitorPass123!"
    monitor_history=600000
    monitor_connect_interval=60000
    monitor_ping_interval=10000
    monitor_read_only_interval=1500
    monitor_read_only_timeout=500
    ping_interval_server_msec=120000
    ping_timeout_server=500
    commands_stats=true
    sessions_sort=true
    connect_retries_on_failure=10
}

mysql_servers =
(
    {
        address = "203.0.113.10"
        port = 3306
        hostgroup = 0
        weight = 1000
        status = "ONLINE"
        compression = 0
        max_connections = 200
        max_replication_lag = 10
        use_ssl = 1
        comment = "MySQL Master Server"
    },
    {
        address = "203.0.113.11"
        port = 3306
        hostgroup = 1
        weight = 900
        status = "ONLINE"
        compression = 0
        max_connections = 200
        max_replication_lag = 10
        use_ssl = 1
        comment = "MySQL Replica Server 1"
    },
    {
        address = "203.0.113.12"
        port = 3306
        hostgroup = 1
        weight = 900
        status = "ONLINE"
        compression = 0
        max_connections = 200
        max_replication_lag = 10
        use_ssl = 1
        comment = "MySQL Replica Server 2"
    }
)

mysql_users:
(
    {
        username = "app_user"
        password = "AppUserPass123!"
        default_hostgroup = 0
        max_connections = 1000
        default_schema = "production_db"
        active = 1
        use_ssl = 1
    },
    {
        username = "read_user"
        password = "ReadUserPass123!"
        default_hostgroup = 1
        max_connections = 500
        default_schema = "production_db"
        active = 1
        use_ssl = 1
    }
)

mysql_query_rules:
(
    {
        rule_id = 1
        active = 1
        match_pattern = "^SELECT.*"
        destination_hostgroup = 1
        apply = 1
        comment = "Route SELECT queries to read replicas"
    },
    {
        rule_id = 2
        active = 1
        match_pattern = "^INSERT|UPDATE|DELETE.*"
        destination_hostgroup = 0
        apply = 1
        comment = "Route write queries to master"
    }
)

Set correct permissions for configuration

Secure the configuration file to protect database credentials. Only the proxysql user and root should have access to sensitive connection details.

sudo chown proxysql:proxysql /etc/proxysql.cnf
sudo chmod 640 /etc/proxysql.cnf

Create MySQL monitor user on backend servers

ProxySQL needs a monitoring user on each MySQL server to perform health checks and read-only detection. Run these commands on each MySQL backend server.

mysql -u root -p << 'EOF'
CREATE USER 'proxysql_monitor'@'%' IDENTIFIED BY 'MonitorPass123!';
GRANT USAGE ON . TO 'proxysql_monitor'@'%';
GRANT SELECT ON performance_schema.* TO 'proxysql_monitor'@'%';
FLUSH PRIVILEGES;
EOF

Start and enable ProxySQL service

Enable ProxySQL to start automatically on boot and start the service. The initial startup will create the SQLite database and apply the configuration.

sudo systemctl enable proxysql
sudo systemctl start proxysql
sudo systemctl status proxysql

Configure connection pool settings

Connect to ProxySQL admin interface and optimize connection pool parameters for your workload. These settings control how connections are managed and reused.

mysql -u proxysql-admin -p'StrongAdminPass123!' -h 127.0.0.1 -P 6032 --prompt='ProxySQL Admin> '

Once connected to the admin interface, run these optimization commands:

UPDATE global_variables SET variable_value='4' WHERE variable_name='mysql-threads';
UPDATE global_variables SET variable_value='2048' WHERE variable_name='mysql-max_connections';
UPDATE global_variables SET variable_value='10000' WHERE variable_name='mysql-free_connections_pct';
UPDATE global_variables SET variable_value='300' WHERE variable_name='mysql-connection_max_age_ms';
UPDATE global_variables SET variable_value='10000' WHERE variable_name='mysql-ping_interval_server_msec';
UPDATE global_variables SET variable_value='500' WHERE variable_name='mysql-ping_timeout_server';
LOAD MYSQL VARIABLES TO RUNTIME;
SAVE MYSQL VARIABLES TO DISK;
exit;

Configure advanced query routing rules

Add more sophisticated routing rules for better load distribution and performance. These rules handle different query patterns and database operations.

mysql -u proxysql-admin -p'StrongAdminPass123!' -h 127.0.0.1 -P 6032 << 'EOF'
INSERT INTO mysql_query_rules (rule_id, active, match_pattern, destination_hostgroup, apply, comment) VALUES
(10, 1, '^SELECT.*FOR UPDATE', 0, 1, 'SELECT FOR UPDATE to master'),
(11, 1, '^SELECT.*LOCK IN SHARE MODE', 0, 1, 'SELECT with shared locks to master'),
(12, 1, '^SELECT.FROM.WHERE.=.LAST_INSERT_ID', 0, 1, 'Queries using LAST_INSERT_ID to master'),
(20, 1, '^SELECT COUNT\\(\\*\\)', 1, 1, 'COUNT queries to replicas'),
(21, 1, '^SELECT.*LIMIT', 1, 1, 'LIMIT queries to replicas'),
(30, 1, '^BEGIN|START TRANSACTION', 0, 1, 'Transactions to master'),
(31, 1, '^COMMIT', 0, 1, 'Commits to master'),
(32, 1, '^ROLLBACK', 0, 1, 'Rollbacks to master');
LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL QUERY RULES TO DISK;
EOF

Configure health check settings

Set up comprehensive health monitoring to detect failed servers and automatically remove them from the pool. This ensures high availability by preventing connections to unhealthy backends.

mysql -u proxysql-admin -p'StrongAdminPass123!' -h 127.0.0.1 -P 6032 << 'EOF'
UPDATE global_variables SET variable_value='2000' WHERE variable_name='mysql-monitor_connect_interval';
UPDATE global_variables SET variable_value='1000' WHERE variable_name='mysql-monitor_ping_interval';
UPDATE global_variables SET variable_value='3' WHERE variable_name='mysql-monitor_ping_max_failures';
UPDATE global_variables SET variable_value='5000' WHERE variable_name='mysql-monitor_ping_timeout';
UPDATE global_variables SET variable_value='1500' WHERE variable_name='mysql-monitor_read_only_interval';
UPDATE global_variables SET variable_value='3' WHERE variable_name='mysql-monitor_read_only_max_timeout_count';
UPDATE global_variables SET variable_value='500' WHERE variable_name='mysql-monitor_read_only_timeout';
LOAD MYSQL VARIABLES TO RUNTIME;
SAVE MYSQL VARIABLES TO DISK;
EOF

Set up ProxySQL stats database

Enable detailed statistics collection for monitoring query performance, connection usage, and identifying bottlenecks. This data is essential for performance tuning.

mysql -u proxysql-admin -p'StrongAdminPass123!' -h 127.0.0.1 -P 6032 << 'EOF'
UPDATE global_variables SET variable_value='true' WHERE variable_name='mysql-commands_stats';
UPDATE global_variables SET variable_value='true' WHERE variable_name='mysql-query_digests';
UPDATE global_variables SET variable_value='true' WHERE variable_name='mysql-query_digests_normalize_digest_text';
UPDATE global_variables SET variable_value='1048576' WHERE variable_name='mysql-query_digests_max_digest_length';
UPDATE global_variables SET variable_value='10000' WHERE variable_name='mysql-query_digests_max_query_length';
LOAD MYSQL VARIABLES TO RUNTIME;
SAVE MYSQL VARIABLES TO DISK;
EOF

Configure log rotation

Set up log rotation to prevent ProxySQL logs from consuming excessive disk space. This maintains system stability in production environments.

/var/lib/proxysql/proxysql.log {
    daily
    missingok
    rotate 7
    compress
    delaycompress
    notifempty
    copytruncate
    su proxysql proxysql
}

Create ProxySQL monitoring script

Build a monitoring script to track ProxySQL performance and backend server health. This provides automated alerting when issues are detected.

#!/bin/bash
set -euo pipefail

ProxySQL monitoring configuration

PROXYSQL_ADMIN_HOST="127.0.0.1" PROXYSQL_ADMIN_PORT="6032" PROXYSQL_ADMIN_USER="proxysql-admin" PROXYSQL_ADMIN_PASS="StrongAdminPass123!" ALERT_EMAIL="admin@example.com" LOG_FILE="/var/log/proxysql-monitor.log"

Function to log messages

log_message() { echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE" }

Function to send alert

send_alert() { local message="$1" log_message "ALERT: $message" echo "$message" | mail -s "ProxySQL Alert - $(hostname)" "$ALERT_EMAIL" }

Check ProxySQL service status

if ! systemctl is-active --quiet proxysql; then send_alert "ProxySQL service is not running" exit 1 fi

Check admin interface connectivity

if ! mysql -h"$PROXYSQL_ADMIN_HOST" -P"$PROXYSQL_ADMIN_PORT" -u"$PROXYSQL_ADMIN_USER" -p"$PROXYSQL_ADMIN_PASS" -e "SELECT 1" >/dev/null 2>&1; then send_alert "Cannot connect to ProxySQL admin interface" exit 1 fi

Check backend server status

OFFLINE_SERVERS=$(mysql -h"$PROXYSQL_ADMIN_HOST" -P"$PROXYSQL_ADMIN_PORT" -u"$PROXYSQL_ADMIN_USER" -p"$PROXYSQL_ADMIN_PASS" -sN -e "SELECT COUNT(*) FROM mysql_servers WHERE status='OFFLINE_HARD' OR status='OFFLINE_SOFT';") if [ "$OFFLINE_SERVERS" -gt 0 ]; then send_alert "$OFFLINE_SERVERS backend MySQL servers are offline" fi

Check connection pool utilization

CONN_USAGE=$(mysql -h"$PROXYSQL_ADMIN_HOST" -P"$PROXYSQL_ADMIN_PORT" -u"$PROXYSQL_ADMIN_USER" -p"$PROXYSQL_ADMIN_PASS" -sN -e "SELECT ROUND(SUM(ConnUsed)/SUM(ConnMax)*100,2) as conn_usage FROM stats_mysql_connection_pool;") if (( $(echo "$CONN_USAGE > 80" | bc -l) )); then send_alert "High connection pool utilization: ${CONN_USAGE}%" fi

Check query response time

AVG_TIME=$(mysql -h"$PROXYSQL_ADMIN_HOST" -P"$PROXYSQL_ADMIN_PORT" -u"$PROXYSQL_ADMIN_USER" -p"$PROXYSQL_ADMIN_PASS" -sN -e "SELECT ROUND(AVG(sum_time/count_star)/1000,2) FROM stats_mysql_query_digest WHERE last_seen > DATE_SUB(NOW(), INTERVAL 5 MINUTE);") if (( $(echo "$AVG_TIME > 1000" | bc -l) )); then send_alert "High average query response time: ${AVG_TIME}ms" fi log_message "ProxySQL monitoring check completed successfully"
sudo chmod +x /usr/local/bin/proxysql-monitor.sh
sudo chown proxysql:proxysql /usr/local/bin/proxysql-monitor.sh

Create systemd timer for monitoring

Set up automated monitoring checks every 5 minutes using systemd timers. This provides continuous health monitoring without requiring cron.

[Unit]
Description=ProxySQL Health Monitor
After=proxysql.service
Requires=proxysql.service

[Service]
Type=oneshot
User=proxysql
Group=proxysql
ExecStart=/usr/local/bin/proxysql-monitor.sh
StandardOutput=journal
StandardError=journal
[Unit]
Description=Run ProxySQL Health Monitor every 5 minutes
Requires=proxysql-monitor.service

[Timer]
OnCalendar=*:0/5
Persistent=true

[Install]
WantedBy=timers.target
sudo systemctl daemon-reload
sudo systemctl enable --now proxysql-monitor.timer
sudo systemctl status proxysql-monitor.timer

Verify your setup

Test ProxySQL functionality and connection pooling to ensure everything is working correctly.

# Check ProxySQL service status
sudo systemctl status proxysql

Verify admin interface connection

mysql -u proxysql-admin -p'StrongAdminPass123!' -h 127.0.0.1 -P 6032 -e "SELECT * FROM mysql_servers;"

Test application connection through ProxySQL

mysql -u app_user -p'AppUserPass123!' -h 127.0.0.1 -P 6033 -e "SELECT @@server_id, @@hostname;"

Check connection pool status

mysql -u proxysql-admin -p'StrongAdminPass123!' -h 127.0.0.1 -P 6032 -e "SELECT * FROM stats_mysql_connection_pool;"

Verify query routing rules

mysql -u proxysql-admin -p'StrongAdminPass123!' -h 127.0.0.1 -P 6032 -e "SELECT rule_id, match_pattern, destination_hostgroup FROM mysql_query_rules WHERE active=1;"

Check backend server health

mysql -u proxysql-admin -p'StrongAdminPass123!' -h 127.0.0.1 -P 6032 -e "SELECT hostname, port, status, ConnUsed, ConnFree, ConnOK, ConnERR FROM mysql_servers JOIN stats_mysql_connection_pool USING(hostgroup_id, srv_host, srv_port);"

Monitor query statistics

mysql -u proxysql-admin -p'StrongAdminPass123!' -h 127.0.0.1 -P 6032 -e "SELECT schemaname, digest_text, count_star, sum_time FROM stats_mysql_query_digest ORDER BY count_star DESC LIMIT 10;"

Configure SSL encryption

Enable SSL for backend connections

Configure ProxySQL to use encrypted connections to MySQL backend servers. This protects data in transit between ProxySQL and your database servers.

mysql -u proxysql-admin -p'StrongAdminPass123!' -h 127.0.0.1 -P 6032 << 'EOF'
UPDATE mysql_servers SET use_ssl=1;
LOAD MYSQL SERVERS TO RUNTIME;
SAVE MYSQL SERVERS TO DISK;
EOF

Configure client SSL certificates

Set up SSL certificates for ProxySQL client connections when security requirements mandate encryption for application-to-proxy communication.

mysql -u proxysql-admin -p'StrongAdminPass123!' -h 127.0.0.1 -P 6032 << 'EOF'
UPDATE global_variables SET variable_value='/etc/ssl/certs/proxysql-server.pem' WHERE variable_name='mysql-ssl_p2s_cert';
UPDATE global_variables SET variable_value='/etc/ssl/private/proxysql-server.key' WHERE variable_name='mysql-ssl_p2s_key';
UPDATE global_variables SET variable_value='/etc/ssl/certs/ca-certificates.crt' WHERE variable_name='mysql-ssl_p2s_ca';
LOAD MYSQL VARIABLES TO RUNTIME;
SAVE MYSQL VARIABLES TO DISK;
EOF

Common issues

Symptom Cause Fix
ProxySQL won't start Configuration syntax error sudo proxysql --initial -f -c /etc/proxysql.cnf to test config
Can't connect to admin interface Wrong credentials or interface binding Check admin_credentials and mysql_ifaces in config
Backend servers show OFFLINE_HARD Monitor user missing or network issues Verify monitor user exists: SHOW GRANTS FOR 'proxysql_monitor'@'%';
Queries not routing correctly Query rules not loaded or pattern mismatch LOAD MYSQL QUERY RULES TO RUNTIME; and check patterns
High connection pool usage max_connections too low or connection leaks Increase max_connections per server in mysql_servers table
SSL connection failures Certificate path wrong or permissions Check certificate files exist and are readable by proxysql user
Monitor checks failing Email not configured or bc calculator missing Install mailutils and bc: sudo apt install mailutils bc
Permission denied on log files Wrong ownership on ProxySQL directories sudo chown -R proxysql:proxysql /var/lib/proxysql
Never use chmod 777. It gives every user on the system full access to your files. Instead, fix ownership with chown and use minimal permissions like 640 for config files and 755 for directories.

Monitor ProxySQL performance

ProxySQL provides extensive statistics tables for monitoring performance, connection usage, and query patterns. Regular monitoring helps identify bottlenecks and optimization opportunities. You can integrate this data with Prometheus and Grafana dashboards for comprehensive database monitoring.

Key metrics to monitor include connection pool utilization, query response times, backend server health, and failed connection attempts. The stats tables update in real-time and provide historical data for trend analysis.

For production deployments, consider implementing automated failover testing and backup strategies. The MySQL replication setup guide covers backend database high availability configuration that complements ProxySQL's connection management.

Next steps

Running this in production?

Want this handled for you? Setting up ProxySQL once is straightforward. Keeping it patched, monitored, backed up and tuned across environments is the harder part. See how we run infrastructure like this for European SaaS and e-commerce teams.

Automated install script

Run this to automate the entire setup

Need help?

Don't want to manage this yourself?

We handle high availability infrastructure for businesses that depend on uptime. From initial setup to ongoing operations.