ProxySQL is a high-performance, high-availability proxy for MySQL, serving as an intermediary between MySQL clients and servers to optimize and manage database traffic. It provides advanced query routing, directing queries to the most appropriate database server based on predefined rules, such as the query type or server load, thus enhancing performance and spreading the load evenly across servers. Open and closing connections in MySQL means creating and deleting new OS threads, which under the

Marcelo Altmann
2024-04-02 · 4 min read
ProxySQL is a high-performance, high-availability proxy for MySQL, serving as an intermediary between MySQL clients and servers to optimize and manage database traffic. It provides advanced query routing, directing queries to the most appropriate database server based on predefined rules, such as the query type or server load, thus enhancing performance and spreading the load evenly across servers.
Open and closing connections in MySQL means creating and deleting new OS threads, which under the hood among other things means allocating and deallocating memory. In a high volume system, this can degrade performance. With this in mind, MySQL has the possibility to re-utilize a connection, via COM_CHANGE_USER (REF). This command from MySQL protocol allows libraries to utilize the same connection for a different user, re-authenticating and avoiding the need of MySQL server to close and open a new connection.
Multiple libraries utilize this approach when returning a connection back to a connection pool, either executing a COM_RESET_CONNECTION (REF) or COM_CHANGE_USER. ProxySQL also utilizes this approach to better utilize the connection resources.
Starting at Readyset version stable-240328 Readyset supports for COM_CHANGE_USER ( commit ) and COM_RESET_CONNECTION ( commit ) allowing users to add Readyset as a mysql server into ProxySQL.
In order to configure ProxySQL to work with Readyset users need to:
SET mysql-monitor_username = 'root';
SET mysql-monitor_password = 'root';
LOAD MYSQL VARIABLES TO RUNTIME;
SAVE MYSQL VARIABLES TO DISK;
mysql_servers table. A good practice here is to also add one or more of your read replicas with a small height, in case Readyset becomes unavailable, the read replica will be serving the read cache traffic:INSERT INTO mysql_servers (hostgroup_id, hostname, port, weight)
VALUES (99, '127.0.0.1', 3307, 1000), (99, '127.0.0.1', 3306, 1);
LOAD MYSQL SERVERS TO RUNTIME;
SAVE MYSQL SERVERS TO DISK;
stats_mysql_query_digest:mysql> SELECT * FROM stats_mysql_query_digest WHERE digest_text
LIKE 'SELECT MIN%'\G
*************************** 1. row ***************************
hostgroup: 11
schemaname: employees
username: root
client_address:
digest: 0xd08a266fffe0340c
digest_text: SELECT MIN(s.salary) FROM salaries s JOIN employees e ON s.emp_no = e.emp_no WHERE e.gender = ?
count_star: 2
first_seen: 1711635175
last_seen: 1711635252
sum_time: 1089964
min_time: 66789
max_time: 1023175
sum_rows_affected: 0
sum_rows_sent: 1
1 row in set (0,00 sec)
mysql> INSERT INTO mysql_query_rules
(username, destination_hostgroup, active, digest, apply)
VALUES
('root', 99, 1, '0xd08a266fffe0340c', 1);
Query OK, 1 row affected (0,00 sec)
mysql> LOAD MYSQL QUERY RULES TO RUNTIME;
Query OK, 0 rows affected (0,00 sec)
mysql> SAVE MYSQL QUERY RULES TO DISK;
Query OK, 0 rows affected (0,01 sec)
mysql> SHOW PROXIED QUERIES\G
*************************** 1. row ***************************
query id: q_309ec37ca1ca3d3
proxied query: SELECT min(`s`.`salary`) FROM `salaries` AS `s` JOIN `employees` AS `e` ON (`s`.`emp_no` = `e`.`emp_no`) WHERE (`e`.`gender` = $1)
readyset supported: yes
count: 0
1 row in set (0,00 sec)
mysql> CREATE CACHE FROM SELECT MIN(s.salary) FROM salaries s
JOIN employees e ON s.emp_no = e.emp_no WHERE e.gender = 'F';
Query OK, 0 rows affected (1,06 sec)
Now the next time we execute the query via ProxySQL it will automatically be served from Readyset Cache:
#### Before ####
mysql> SELECT MIN(s.salary) FROM salaries s JOIN employees e ON s.emp_no = e.emp_no WHERE e.gender = 'F';
+---------------+
| MIN(s.salary) |
+---------------+
| 38786 |
+---------------+
1 row in set (1,03 sec)
#### After ####
mysql> SELECT MIN(s.salary) FROM salaries s JOIN employees e ON s.emp_no = e.emp_no WHERE e.gender = 'F';
+--------------------------------------+
| min(`employees`.`salaries`.`salary`) |
+--------------------------------------+
| 38786 |
+--------------------------------------+
1 row in set (0,00 sec)
Query response time dropped from 1 second to less than a millisecond.
Summary
Starting at Readyset version stable-240328 is now possible to integrate Readyset with ProxySQL. Users can still benefit from all the ProxySQL functionalities like transparent query routing and align it with the performance boost Readyset can bring to your MySQL read workloads. All 100% transparent to applications without requiring a single line of code change.
If you use MySQL and want a fully-managed version of Readyset in production to improve the performance of your workloads, we can help make that happen. We've launched a MySQL design partner program to assist with a production-ready implementation of Readyset Cloud and to continue expanding our MySQL compatibility!
As a design partner, you will offer direct influence on our MySQL-compatibility roadmap.Spots are limited. Schedule time today.
Modern applications demand instant performance, even under unpredictable load. Readyset helps you eliminate slow queries, stabilize latency, and scale confidently.
Revolutionize your database performance with Readyset
Serve requests at sub-millisecond latencies with the modern database scaling and query caching system for MySQL and PostgreSQL.
Join our newsletter
Stay updated with the latest news, insights, and developments from Readyset — straight to your inbox.