ProxySQL:实现MySQL8.0主从同步与读写分离
文章目录
- Mysql8.0主从同步与读写分离
- 一、数据库主从同步与读写分离的意义
- 1.核心目标
- 2. 关键实施步骤
- 二、实现数据库主从同步操作
- 1. 环境准备
- 2. 搭建数据库
- 3. 启动主从同步
- 三、 ProxySQL实现读写分离
- 1. ProxySQL介绍
- 2. ProxySQL的Admin管理接口
- 3. ProxySQL实现读写分离
Mysql8.0主从同步与读写分离
一、数据库主从同步与读写分离的意义
1.核心目标
- 实现数据库层面的读写分离,提升整体并发处理能力和响应速度,优化单体应用的数据库访问性能;
- 通过自动化定期备份,保障数据安全,降低误操作或故障导致的数据丢失风险,确保数据可恢复和可追溯。
2. 关键实施步骤
-
读写分离配置
-
- 采用数据库中间件(如ProxySQL、MyCat)或在业务代码层实现数据库读写分离。
- 写操作(如INSERT、UPDATE、DELETE)统一路由到主库,读操作(如SELECT)智能分发到从库。
- 配置和优化主库与从库的数据同步机制,确保数据一致性与及时性。
- 定期监测主从同步延迟和健康状态,设置自动告警,及时发现并处理读写分离中的异常情况。
- 对于高并发场景,可以根据实际业务量调整从库数量,实现负载均衡。
- 在应用层实现透明切换,主库故障时可自动切换到可用节点。
-
定期备份脚本开发与部署
-
- 编写Shell脚本,定时对数据库进行全量或增量备份,备份内容包括数据文件、binlog等关键数据。
- 脚本支持自动归档、压缩,并将备份文件推送到本地备份目录和异地/云端存储,提升数据安全性。
- 设置定期清理过期备份文件,防止磁盘空间不足。
- 备份任务结果自动邮件、飞书等告警推送,保障备份异常及时发现。
二、实现数据库主从同步操作
1. 环境准备
操作系统 | Ubuntu22.04(云服务器) |
---|---|
数据库版本 | Mysql 8.0.23 |
主从思想 | 主库使用apt安装,从库使用Docker运行 |
网络 | 内网实现细节,外网进行访问 |
2. 搭建数据库
搭建本地数据库:
# 安装
apt install -y mysql-server-8.0
systemctl start mysql
systemctl enable mysql# MySQL安装成功后,设置root密码并创建应用用户
mysql -u root << 'EOF'
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';
CREATE USER IF NOT EXISTS 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'password';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION;
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';
FLUSH PRIVILEGES;FLUSH PRIVILEGES;
SELECT 'All users and authentication plugins set successfully!' as Result;
EOFsudo systemctl daemon-reload
sudo systemctl start mysql
sudo systemctl status mysql
创建从库所需文件目录:
# 创建用于持久化存储的目录结构
sudo mkdir -p /data/mysql/docker/{mysql-slave/data,mysql-slave/conf,mysql-slave/logs}# 服务写入权限
sudo chown -R 999:999 /data/mysql/docker/mysql-slave/
sudo chmod -R 755 /data/mysql/docker/mysql-slave/
创建MySQL从库的配置文件 /data/mysql/docker/mysql-slave/conf/my.cnf
,内容如下:
[mysqld]
# 网络与连接
port=3306
skip-name-resolve
max_connections=10000# 字符集与默认设置
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
default-storage-engine=INNODB
default_authentication_plugin=mysql_native_password
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION# 时区
default-time-zone='+8:00'# 复制角色配置(关键)
server-id=2
read_only=ON
# 中继日志配置
relay-log=relay-log
relay-log-index=relay-log.index# 二进制日志配置(建议从库也开启,便于故障恢复后接力)
log-bin=mysql-binlog
binlog-format=ROW# 日志配置
log-error=/var/log/mysql/error.log
slow_query_log=ON
slow_query_log_file=/var/log/mysql/slow.log
long_query_time=2
skip-grant-tables
主库开启访问权限:
vim /etc/mysql/mysql.conf.d/mysqld.cnf
bind-address = 0.0.0.0
创建从库容器:
# 创建并启动容器
docker run -d --name mysql-slave --restart=unless-stopped -p 3307:3306 -v /data/mysql/docker/mysql-slave/data:/var/lib/mysql -v /data/mysql/docker/mysql-slave/conf:/etc/mysql/conf.d -v /data/mysql/docker/mysql-slave/logs:/var/log/mysql -e MYSQL_ROOT_PASSWORD=password mysql:8.0.23# 验证服务运行
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ea13359fcb9d mysql:8.0.23 "docker-entrypoint.s…" 3 hours ago Up 3 hours 33060/tcp, 0.0.0.0:3307->3306/tcp, [::]:3307->3306/tcp mysql-slave
创建从库密码:
FLUSH PRIVILEGES;ALTER USER 'root'@'localhost' IDENTIFIED BY 'password';
ALTER USER 'root'@'%' IDENTIFIED BY 'password';ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'password';FLUSH PRIVILEGES;exit;
退出后,删除skip-grant-tables权限,重启从库:
vim /data/mysql/docker/mysql-slave/conf/my.cnf
# 删除
skip-grant-tables# 重启数据库
docker restart mysql-slave
3. 启动主从同步
主从配置思路:
通信方向 | 推荐网络 | IP类型 | 优点 |
---|---|---|---|
主库 ↔ 从库 | 内网 | 内网IP | 低延迟、高带宽、安全、免费 |
应用程序 ↔ ProxySQL | 公网 | 公网IP | 便于外部访问 |
ProxySQL ↔ 主库/从库 | 内网 | 内网IP | 低延迟、高带宽、安全、免费 |
内网IP为:192.168.116.2,我们开始配置。
主库创建同步用户:
CREATE USER 'repl'@'%' IDENTIFIED WITH mysql_native_password BY 'repl_password';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;
SHOW MASTER STATUS; # 记录下 File 和 Position
从库配置连接:
CHANGE MASTER TO
MASTER_HOST='192.168.116.2',
MASTER_USER='repl',
MASTER_PASSWORD='repl_password',
MASTER_LOG_FILE='上一步记录的File',
MASTER_LOG_POS=上一步记录的Position;# 验证同步状态
START SLAVE;
SHOW SLAVE STATUS\G;
同步成功。
进行测试:
在主库创建一个数据库,在从库进行查询:
# 自己试试,肯定是成功的奥。
CREATE DATABASES TESTDB;
EXIT;SHOW DATABASES;
三、 ProxySQL实现读写分离
1. ProxySQL介绍
ProxySQL是灵活强大的MySQL代理层, 是一个能实实在在用在生产环境的MySQL中间件,可以实现读写分离,支持 Query 路由功能,支持动态指定某个 SQL 进行 cache,支持动态加载配置、故障切换和一些 SQL的过滤功能。
还有一些同类产品比如 DBproxy、MyCAT、OneProxy 等。但经过反复对比和测试之后,还是觉得ProxySQL是一款性能不谙,靠谱稳定的MySQL 中间件产品.它有官方版和 percona 版两种.percona版是在官方版的基础上修改的,添加了几个比较实用的工具。生产环境建议用官方版。ProxySQL 是用 C++ 语言开发的,虽然也是一个轻量级产品。
维度 | 说明 |
---|---|
本质 | 七层 MySQL 协议网关(L7 MySQL Gateway) |
语言 | C++11 单线程事件模型(epoll/kqueue),内置 jemalloc |
角色 | 只做“路由 + 连接池 + 防火墙”,不做分片;可横向扩展,无状态 |
竞品差异 | 与 ShardingSphere 相比:无分片逻辑,性能更高;与 MyCAT 相比:支持在线变更、规则粒度更细 |
官方上限 | 单核 400 kQPS(SELECT_PK),连接数 1 M(受内存限制),延迟 100 μs 级 |
2. ProxySQL的Admin管理接口
当Proxysql启动后,将监听两个端口:
- admin管理接口,默认端口为6032。该端口用于查看、配置ProxySQL
- 接收SQL语句的接口,默认端口为6033,这个接口类似于MySQL的3306端口
ProxySQL自身共有5个库,分别为3个保存在内存中的库,和2个保存在磁盘的SQLite库。
通过6032管理端口登入后,默认就是main库,所有的配置更改都必须在这个库中进行,disk存档库不会直接受到影响。
root@hzy-baidubcc:~# mysql -uadmin -padmin -h127.0.0.1 -P6032
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.5.30 (ProxySQL Admin Module)Copyright (c) 2000, 2025, Oracle and/or its affiliates.Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql> show databases;
+-----+---------------+-------------------------------------+
| seq | name | file |
+-----+---------------+-------------------------------------+
| 0 | main | |
| 2 | disk | /var/lib/proxysql/proxysql.db |
| 3 | stats | |
| 4 | monitor | |
| 5 | stats_history | /var/lib/proxysql/proxysql_stats.db |
+-----+---------------+-------------------------------------+
5 rows in set (0.00 sec)mysql>
- main:内存配置数据库,表里存放后端db实例、用户验证、路由规则等信息。表名以 runtime开头的表示proxysql当前运行的配置内容,不能通过dml语句修改,只能修改对应的不以 runtime 开头的(在内存)里的表,然后 LOAD 使其生效, SAVE 使其存到硬盘以供下次重启加载。
- disk:是持久化到硬盘的配置,sqlite数据文件。SQLite3 数据库,默认位置为 $(DATADIR)/proxysql.db,在重新启动时,未保留的内存中配置将丢失。因此,将配置保留在 DISK 中非常重要。(SQLite是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎)
- stats:proxysql运行抓取的统计信息,包括到后端各命令的执行次数、流量、processlist、查询种类汇总/执行时间等等。
- monitor:库存储 monitor 模块收集的信息,主要是对后端db的健康/延迟检查。
- stats_history:统计信息历史库
3. ProxySQL实现读写分离
安装ProxySQL:
# 添加 ProxySQL 仓库
wget -O - 'https://repo.proxysql.com/ProxySQL/repo_pub_key' | apt-key add -
echo deb https://repo.proxysql.com/ProxySQL/proxysql-2.4.x/$(lsb_release -sc)/ ./ | tee /etc/apt/sources.list.d/proxysql.list# 安装
apt-get update
apt-get install proxysql
安装完成后启动ProxySQL:
root@hzy-baidubcc:~# systemctl start proxysql
root@hzy-baidubcc:~# netstat -lnpt | grep proxysql
tcp 0 0 0.0.0.0:6033 0.0.0.0:* LISTEN 39853/proxysql
tcp 0 0 0.0.0.0:6033 0.0.0.0:* LISTEN 39853/proxysql
tcp 0 0 0.0.0.0:6033 0.0.0.0:* LISTEN 39853/proxysql
tcp 0 0 0.0.0.0:6033 0.0.0.0:* LISTEN 39853/proxysql
tcp 0 0 0.0.0.0:6032 0.0.0.0:* LISTEN 39853/proxysql
root@hzy-baidubcc:~#
安装完成,登陆proxysql
root@hzy-baidubcc:~# mysql -uadmin -padmin -h127.0.0.1 -P6032
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.5.30 (ProxySQL Admin Module)Copyright (c) 2000, 2025, Oracle and/or its affiliates.Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql>
配置后端服务器:
mysql> INSERT INTO mysql_servers(hostgroup_id, hostname, port) VALUES (10, '192.168.16.2', 3306);
Query OK, 1 row affected (0.00 sec)mysql> INSERT INTO mysql_servers(hostgroup_id, hostname, port) VALUES (20, '192.168.16.2', 3307);
Query OK, 1 row affected (0.00 sec)mysql> LOAD MYSQL SERVERS TO RUNTIME;
Query OK, 0 rows affected (0.01 sec)mysql> SAVE MYSQL SERVERS TO DISK;
Query OK, 0 rows affected (0.02 sec)
ProxySQL需要监控后端MySQL状态。在配置监控之前,必须先在MySQL主从库上创建监控用户:
# 在主库和从库上分别执行以下命令创建监控用户
mysql -h 192.168.16.2 -P 3306 -u root -p-- 创建监控用户
CREATE USER 'monitor'@'%' IDENTIFIED WITH mysql_native_password BY 'monitor_password';
GRANT REPLICATION CLIENT ON *.* TO 'monitor'@'%';
FLUSH PRIVILEGES;# 在从库上也执行相同的操作
mysql -h 192.168.16.2 -P 3307 -u root -p-- 创建监控用户
CREATE USER 'monitor'@'%' IDENTIFIED WITH mysql_native_password BY 'monitor_password';
GRANT REPLICATION CLIENT ON *.* TO 'monitor'@'%';
FLUSH PRIVILEGES;
配置监控 ,ProxySQL需要监控后端MySQL状态:
UPDATE global_variables SET variable_value='monitor' WHERE variable_name='mysql-monitor_username';
UPDATE global_variables SET variable_value='monitor_password' WHERE variable_name='mysql-monitor_password';
LOAD MYSQL VARIABLES TO RUNTIME;
配置应用用户 (mysql_users)
INSERT INTO mysql_users(username, password, default_hostgroup) VALUES
('app_user', 'app_password', 10);LOAD MYSQL USERS TO RUNTIME;
SAVE MYSQL USERS TO DISK;
确保此用户 (app_user
) 在后端MySQL主从库上真实存在,且使用 mysql_native_password
认证插件。
ALTER USER 'app_user'@'%' IDENTIFIED WITH mysql_native_password BY 'app_password';
配置读写分离规则:
INSERT INTO mysql_query_rules(rule_id, active, match_digest, destination_hostgroup, apply) VALUES
(1, 1, '^SELECT.*FOR UPDATE', 10, 1), -- SELECT FOR UPDATE 去写组
(2, 1, '^SELECT', 20, 1); -- 普通SELECT去读组LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL QUERY RULES TO DISK;
验证配置:
mysql> SELECT * FROM mysql_servers;
+--------------+--------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
| hostgroup_id | hostname | port | gtid_port | status | weight | compression | max_connections | max_replication_lag | use_ssl | max_latency_ms | comment |
+--------------+--------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
| 10 | 192.168.16.2 | 3306 | 0 | ONLINE | 1 | 0 | 1000 | 0 | 0 | 0 | |
| 20 | 192.168.16.2 | 3307 | 0 | ONLINE | 1 | 0 | 1000 | 0 | 0 | 0 | |
+--------------+--------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
2 rows in set (0.00 sec)mysql> SELECT username, hostname, default_hostgroup FROM mysql_users;
ERROR 1045 (28000): ProxySQL Admin Error: no such column: hostname
mysql> SELECT rule_id, active, match_digest, destination_hostgroup FROM mysql_query_rules;
+---------+--------+---------------------+-----------------------+
| rule_id | active | match_digest | destination_hostgroup |
+---------+--------+---------------------+-----------------------+
| 1 | 1 | ^SELECT.*FOR UPDATE | 10 |
| 2 | 1 | ^SELECT | 20 |
+---------+--------+---------------------+-----------------------+
2 rows in set (0.00 sec)mysql> SELECT * FROM monitor.mysql_server_ping_log ORDER BY time_start_us DESC LIMIT 6;
+--------------+------+------------------+----------------------+------------+
| hostname | port | time_start_us | ping_success_time_us | ping_error |
+--------------+------+------------------+----------------------+------------+
| 192.168.16.2 | 3306 | 1758784463723891 | 96 | NULL |
| 192.168.16.2 | 3307 | 1758784463608377 | 153 | NULL |
| 192.168.16.2 | 3306 | 1758784453791495 | 116 | NULL |
| 192.168.16.2 | 3307 | 1758784453608079 | 161 | NULL |
| 192.168.16.2 | 3307 | 1758784443756115 | 167 | NULL |
| 192.168.16.2 | 3306 | 1758784443607681 | 86 | NULL |
+--------------+------+------------------+----------------------+------------+
6 rows in set (0.00 sec)mysql> SELECT * FROM global_variables WHERE variable_name LIKE 'mysql-monitor_%';
+----------------------------------------------------------------------+----------------+
| variable_name | variable_value |
+----------------------------------------------------------------------+----------------+
| mysql-monitor_enabled | true |
| mysql-monitor_connect_timeout | 600 |
| mysql-monitor_ping_max_failures | 3 |
| mysql-monitor_ping_timeout | 1000 |
| mysql-monitor_read_only_max_timeout_count | 3 |
| mysql-monitor_replication_lag_group_by_host | false |
| mysql-monitor_replication_lag_interval | 10000 |
| mysql-monitor_replication_lag_timeout | 1000 |
| mysql-monitor_replication_lag_count | 1 |
| mysql-monitor_groupreplication_healthcheck_interval | 5000 |
| mysql-monitor_groupreplication_healthcheck_timeout | 800 |
| mysql-monitor_groupreplication_healthcheck_max_timeout_count | 3 |
| mysql-monitor_groupreplication_max_transactions_behind_count | 3 |
| mysql-monitor_groupreplication_max_transactions_behind_for_read_only | 1 |
| mysql-monitor_galera_healthcheck_interval | 5000 |
| mysql-monitor_galera_healthcheck_timeout | 800 |
| mysql-monitor_galera_healthcheck_max_timeout_count | 3 |
| mysql-monitor_replication_lag_use_percona_heartbeat | |
| mysql-monitor_query_interval | 60000 |
| mysql-monitor_query_timeout | 100 |
| mysql-monitor_slave_lag_when_null | 60 |
| mysql-monitor_threads_min | 8 |
| mysql-monitor_threads_max | 128 |
| mysql-monitor_threads_queue_maxsize | 128 |
| mysql-monitor_local_dns_cache_ttl | 300000 |
| mysql-monitor_local_dns_cache_refresh_interval | 60000 |
| mysql-monitor_local_dns_resolver_queue_maxsize | 128 |
| mysql-monitor_wait_timeout | true |
| mysql-monitor_writer_is_also_reader | true |
| mysql-monitor_username | monitor |
| mysql-monitor_password | monitor |
| mysql-monitor_history | 600000 |
| mysql-monitor_connect_interval | 60000 |
| mysql-monitor_ping_interval | 10000 |
| mysql-monitor_read_only_interval | 1500 |
| mysql-monitor_read_only_timeout | 500 |
+----------------------------------------------------------------------+----------------+
36 rows in set (0.00 sec)
连接测试:通过ProxySQL的业务端口(6033)连接:
mysql -u app_user -papp_password -h 127.0.0.1 -P 6033
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 14
Server version: 5.5.30 (ProxySQL)Copyright (c) 2000, 2025, Oracle and/or its affiliates.Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql>
测试读写分离
mysql> INSERT INTO test_table (id, name) VALUES (1, 'Test User 1');
Query OK, 1 row affected (0.00 sec)mysql> INSERT INTO test_table (id, name) VALUES (2, 'Test User 2');
Query OK, 1 row affected (0.00 sec)mysql> SELECT * FROM test_table;
+----+-------------+
| id | name |
+----+-------------+
| 1 | Test User 1 |
| 2 | Test User 2 |
+----+-------------+
2 rows in set (0.00 sec)mysql> UPDATE test_table SET name = 'Updated User' WHERE id = 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0mysql> SELECT * FROM test_table;
+----+--------------+
| id | name |
+----+--------------+
| 1 | Updated User |
| 2 | Test User 2 |
+----+--------------+
2 rows in set (0.00 sec)mysql> SELECT * FROM test_table FOR UPDATE;
+----+--------------+
| id | name |
+----+--------------+
| 1 | Updated User |
| 2 | Test User 2 |
+----+--------------+
2 rows in set (0.00 sec)mysql> exit
Bye
root@hzy-baidubcc:~#
验证:在ProxySQL管理界面(6032)查看查询路由统计,确认 SELECT
语句主要出现在hostgroup 20(从库),而 INSERT
、UPDATE
、DELETE
等出现在hostgroup 10(主库)。
mysql> SELECT hostgroup, count_star, digest_text -> FROM stats.stats_mysql_query_digest -> ORDER BY count_star DESC;
+-----------+------------+------------------------------------------------------------------------------+
| hostgroup | count_star | digest_text |
+-----------+------------+------------------------------------------------------------------------------+
| 10 | 5 | select @@version_comment limit ? |
| 20 | 3 | SELECT * FROM test_table |
| 10 | 3 | show databases |
| 20 | 3 | SELECT DATABASE() |
| 10 | 3 | show tables |
| 10 | 2 | INSERT INTO test_table (id,name) VALUES (?,?) |
| 10 | 2 | CREATE TABLE IF NOT EXISTS test_table ( id INT PRIMARY KEY, name VARCHAR(?)) |
| 10 | 2 | CREATE TABLE IF NOT EXISTS test_table ( id INT PRIMARY KEY, name VARCHAR(?)) |
| 10 | 1 | SELECT * FROM test_table FOR UPDATE |
| 10 | 1 | UPDATE test_table SET name = ? WHERE id = ? |
| 20 | 1 | SELECT * FROM `test_table` WHERE ?=? |
| 10 | 1 | show databases |
| 10 | 1 | CREATE TABLE IF NOT EXISTS test_table (id INT PRIMARY KEY,name VARCHAR(?)) |
+-----------+------------+------------------------------------------------------------------------------+
13 rows in set (0.00 sec)mysql> SELECT hostgroup, srv_host, status, ConnUsed, ConnFree, ConnOK, ConnERR -> FROM stats.stats_mysql_connection_pool;
+-----------+--------------+--------+----------+----------+--------+---------+
| hostgroup | srv_host | status | ConnUsed | ConnFree | ConnOK | ConnERR |
+-----------+--------------+--------+----------+----------+--------+---------+
| 10 | 192.168.16.2 | ONLINE | 0 | 1 | 1 | 198 |
| 20 | 192.168.16.2 | ONLINE | 0 | 1 | 1 | 44 |
+-----------+--------------+--------+----------+----------+--------+---------+
2 rows in set (0.00 sec)mysql> SELECT hostgroup, digest_text, count_star, -> sum_time, min_time, max_time, -> sum_rows_affected, sum_rows_sent-> FROM stats.stats_mysql_query_digest-> ORDER BY sum_time DESC-> LIMIT 10;
+-----------+------------------------------------------------------------------------------+------------+----------+----------+----------+-------------------+---------------+
| hostgroup | digest_text | count_star | sum_time | min_time | max_time | sum_rows_affected | sum_rows_sent |
+-----------+------------------------------------------------------------------------------+------------+----------+----------+----------+-------------------+---------------+
| 10 | show databases | 3 | 79742 | 1458 | 53026 | 0 | 5 |
| 10 | CREATE TABLE IF NOT EXISTS test_table ( id INT PRIMARY KEY, name VARCHAR(?)) | 2 | 79354 | 25823 | 53531 | 0 | 0 |
| 10 | show tables | 3 | 74911 | 1011 | 51457 | 0 | 1 |
| 10 | CREATE TABLE IF NOT EXISTS test_table ( id INT PRIMARY KEY, name VARCHAR(?)) | 2 | 61766 | 7889 | 53877 | 0 | 0 |
| 20 | SELECT DATABASE() | 3 | 50589 | 817 | 36272 | 0 | 1 |
| 10 | show databases | 1 | 26395 | 26395 | 26395 | 0 | 0 |
| 10 | CREATE TABLE IF NOT EXISTS test_table (id INT PRIMARY KEY,name VARCHAR(?)) | 1 | 25152 | 25152 | 25152 | 0 | 0 |
| 10 | INSERT INTO test_table (id,name) VALUES (?,?) | 2 | 6936 | 3196 | 3740 | 2 | 0 |
| 10 | UPDATE test_table SET name = ? WHERE id = ? | 1 | 4639 | 4639 | 4639 | 1 | 0 |
| 20 | SELECT * FROM test_table | 3 | 1247 | 350 | 483 | 0 | 4 |
+-----------+------------------------------------------------------------------------------+------------+----------+----------+----------+-------------------+---------------+
10 rows in set (0.00 sec)mysql>
查询类型/模式 (digest_text) | 执行次数 (count_star) | 总耗时 (sum_time, μs) | 路由分组 (hostgroup) | 性能分析 |
---|---|---|---|---|
show databases | 4 | 106,137 μs | 10 (主库) | 管理命令,耗时正常 |
CREATE TABLE ... | 5 | 166,272 μs | 10 (主库) | DDL操作,耗时正常 |
show tables | 3 | 74,911 μs | 10 (主库) | 管理命令,耗时正常 |
SELECT DATABASE() | 3 | 50,589 μs | 20 (从库) | 读操作,成功分离至从库 |
INSERT INTO ... | 2 | 6,936 μs | 10 (主库) | 写操作,成功路由至主库 |
UPDATE ... | 1 | 4,639 μs | 10 (主库) | 写操作,成功路由至主库 |
SELECT * FROM test_table | 3 | 1,247 μs | 20 (从库) | 读操作,成功分离至从库,效率高 |
SELECT * FROM test_table FOR UPDATE | 1 | (未在TOP10) | 10 (主库) | 特殊读操作(加写锁),正确路由至主库 |
至此,使用ProxySQL实现读写分离配置完成。