目录

一、mysql双主双从(MM-SS)

环境准备

搭建步骤

两个主服务器

1.编辑配置文件

2.创建用户

3.设置主服务器

4.启动

5.测试

从服务器配置

1.恢复主服务器备份

2.修改配置文件

3.设置双主复制通道

4.启动

二、ProxySQL读写分离

1.安装 ProxySQL

方法1:使用官方 YUM 仓库

方法2:配置官方仓库

2.配置防火墙

3.proxySql的基础配置

3.1连接到管理界面

3.2.配置监控用户

3.4.配置Mysql用户(用于应用连接)

3.6.保存配置

4.测试

4.1.检查服务器状态

4.2.检查连接监控

4.3测试应用连接


一、mysql双主双从(MM-SS)

mysql双主双从,顾名思义,就是有两个主服务器,两个(或多个)从服务器。单个主服务器如果故障,会影响全局的写入事件。双主服务器可以解决这个问题。

环境准备

在测试环境中,关闭所有主机的防火墙,selinux设置为关闭。所有主机已安装mysql5.7.17版本

主机名

IP地址

master1

192.168.4.50

master2

192.168.4.51

slave1

192.168.4.52

slave2

192.168.4.53

搭建步骤

两个主服务器

接下来需要分别在各个服务器上设置对方为自己的主服务器。

1.编辑配置文件

打开主配置文件/etc/my.cnf。向其中写入:

master1:

[mysqld]
server_id=1
log-bin = mysql-bin
binlog-format = ROW
gtid_mode=ON
enforce_gtid_consistency=1
auto-increment-increment=2
auto-increment-offset=1
log-bin=mysql-bin
sync_binlog=1

master2

[mysqld]
server_id=2
log-bin = mysql-bin
binlog-format = ROW
gtid_mode=ON
enforce_gtid_consistency=1
auto-increment-increment=2
auto-increment-offset=2
log-bin=mysql-bin
sync_binlog=1

编辑完后记得重启mysql

上面的配置中设置了GTID,设置后,从服务器会自动与主服务器协商二进制日志的复制位置,不用在自行查看主服务器的配置。避免出现位置错误

GTID(全局事务标识符)是MySQL复制中的一种机制,它为每个事务生成一个全局唯一的ID,用于自动追踪和定位复制位置。使用GTID后,不再需要手动指定二进制日志文件名和位置,简化了主从切换和故障恢复的流程。当主库发生故障时,从库可以根据GTID自动找到正确的事务点继续复制,确保数据一致性和高可用性。

配置文件中auto-increment-increment(自增步长)和auto-increment-offset(自增偏移量)是GTID相关的重要配置项。这是为了避免双主服务器同时写入时自增主键冲突。每次新增事务时,GTID会按照自增步长增加,并根据来源服务器的不同偏移相对应的值。(Master1 只会生成 1, 3, 5, 7... 这样的奇数ID,而 Master2 只会生成 2, 4, 6, 8... 这样的偶数ID。)

下面是各字段的解释

字段名

描述

server-id

服务器的id。server-id必须唯一

log-bin

开启二进制日志

binlog-format

设置为ROW,表示使用行格式的二进制日志

gtid_mode = ON

开启GTID(全局事务标识符),这样可以自动跟踪复制位置,避免使用传统的文件名和位置。

enforce-gtid-consistency = ON

确保只有对GTID安全的语句被记录。

auto-increment-increment

自增步长。这是为了避免双主服务器同时写入时自增主键冲突。每次自增这个数值(写主服务器数量)

auto-increment-offset

自增偏移量。每次自增时额外增加这个值。(写服务器序号)

sync_binlog

确保二进制日志及时写入磁盘

2.创建用户

创建master1上创建用于复制的用户

GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'rep'@'192.168.4.%' IDENTIFIED BY 'Xthy@1234';

master2上同理(可以沿用上面的命令)

3.设置主服务器

设置master1服务器的主服务器是master2

在master1上执行

CHANGE MASTER TO
MASTER_HOST='192.168.4.51',
MASTER_USER='rep',
MASTER_PASSWORD='Xthy@1234',
MASTER_AUTO_POSITION=1;

设置master2服务器的主服务器是master1

在master2上编辑

CHANGE MASTER TO
MASTER_HOST='192.168.4.50',
MASTER_USER='rep',
MASTER_PASSWORD='Xthy@1234',
MASTER_AUTO_POSITION=1;

4.启动

START SLAVE;

检查启动状况

SHOW SLAVE STATUS\G;

重点检查这两个字段。如果出错,大概率是刚刚敲的命令有误,可以重新配置一下

Slave_IO_Running: Yes

Slave_SQL_Running: Yes

这样就成功将服务器A设置为服务器B的主服务器了。

5.测试

创建一些临时数据,由于两个主服务器互为主从,在任意一方写入的数据都会同步到另一方

create database test;
use test;
create table user(id int);
insert into user (name) values ('aaa'),('bbb'),('ccc');

mysql> select * from user;
+----+------+
| id | name |
+----+------+
|  1 | aaa  |
|  3 | bbb  |
|  5 | ccc  |
+----+------+
3 rows in set (0.00 sec)

到另一个主机上查询一下

select * from test.user;

这样即使数据没及时同步,主键也不会冲突

设置互为主从后,备份一下,一会儿需要导入到从服务器中

innobackupex --user=root --password='mysqlpassword' /xtrabackup/full/

tar -czf mysqlbackup.tar.gz /xtrabackup/full/2025-10-19_18-30-10/

scp mysqlbackup.tar.gz 192.168.4.52:/root
scp mysqlbackup.tar.gz 192.168.4.53:/root

从服务器配置

1.恢复主服务器备份

(工作目录在/root下)

tar -xf  mysqlbackup.tar.gz
systemctl stop mysqld
rm -rf  /var/lib/mysql/*

innobackupex xtrabackup/full/2025-10-19_18-30-10/ --apply-log
innobackupex xtrabackup/full/2025-10-19_18-30-10/ --copy-back

chown -R  mysql:mysql /var/lib/mysql

systemctl restart mysqld

2.修改配置文件

编辑/etc/my.cnf,在其中分别写入:

slave1

[mysqld]
server-id=3 
gtid_mode=on
enforce_gtid_consistency=1
master-info-repository=TABLE
relay-log-info-repository=TABLE

slave2

[mysqld]
server-id=4
gtid_mode=on
enforce_gtid_consistency=1
master-info-repository=TABLE
relay-log-info-repository=TABLE

重启服务

3.设置双主复制通道

多源复制通道是MySQL中允许一个从服务器同时从多个主服务器复制数据的技术,每个主服务器的数据流通过独立的“通道”进行管理。通道名称用于区分不同主库的数据来源,使得从库可以并行接收和处理多个主库的二进制日志事件。这种机制在双主或多主架构中非常有用,能够实现数据的集中备份、复杂拓扑结构的灵活管理,并支持按通道独立监控和控制复制状态。

--to master1
CHANGE MASTER TO
MASTER_HOST='192.168.4.50',
MASTER_USER='rep',
MASTER_PASSWORD='Xthy@1234',
MASTER_AUTO_POSITION=1 FOR CHANNEL 'master1';

--to master2
CHANGE MASTER TO
MASTER_HOST='192.168.4.51',
MASTER_USER='rep',
MASTER_PASSWORD='Xthy@1234',
MASTER_AUTO_POSITION=1 FOR CHANNEL 'master2';

由于之前设置了GTID,所以这里可以直接设置MASTER_AUTO_POSITION=1 而不是MASTER_LOG_FILE="master*****",MASTER_LOG_POS=***;

按照架构图,slave1应该设置master1通道,slave2应该设置master2通道。但是,一个服务器也可以同时配置多个主服务器的位置,且不影响原有功能

4.启动

START SLAVE;

检查启动状况

SHOW SLAVE STATUS\G;

和刚刚一样关注这两个字段

Slave_IO_Running: Yes

Slave_SQL_Running: Yes

设置完成后,可以插入数据测试一下

在任意主服务器插入数据后,其他服务器也会有数据

主服务器

其他服务器

二、ProxySQL读写分离

接下来我们实现读写分离。可以使用的软件很多,我们这里以ProxySQL为例

1.安装 ProxySQL

方法1:使用官方 YUM 仓库

wget https://github.com/sysown/proxysql/releases/download/v2.5.4/proxysql-2.5.4-1-centos7.x86_64.rpm
yum install -y proxysql-2.5.4-1-centos7.x86_64.rpm

方法2:配置官方仓库

如果上面的方案不可行,那可以试试配置一个官方仓库,内容如下

[proxysql]
name=ProxySQL YUM repository
baseurl=https://repo.proxysql.com/ProxySQL/proxysql-2.5.x/centos/\$releasever
gpgcheck=1
gpgkey=https://repo.proxysql.com/ProxySQL/proxysql-2.5.x/repo_pub_key
yum install -y proxysql

安装成功后,启用服务

systemctl enable proxysql --now

2.配置防火墙

proxySQL 需要占用6032(管理端口),6033(代理端口),6080(web管理端口,如果启动了的话)。如果防火墙开启,则需开放这些端口。

firewall-cmd --permanent --add-port=6032/tcp  
firewall-cmd --permanent --add-port=6033/tcp
firewall-cmd --permanent --add-port=6080/tcp
firewall-cmd --reload
systemctl stop firewalld

我使用的测试环境,防火墙已经关闭

systemctl stop firewalld

3.proxySql的基础配置

3.1连接到管理界面

(如果没安装mysql,这里可以安装一个mariadb)

mysql -u admin -padmin -h 127.0.0.1 -P 6032 --prompt="ProxySQL> "

3.2.配置监控用户

在主服务器上创建监控用户。这个用户是用于服务器之间同步数据的。

GRANT USAGE ON *.* TO 'monitor'@'%' IDENTIFIED BY 'Monitor123!';

FLUSH PRIVILEGES;

然后回到之前连接到的管理界面,在其中配置监控用户:

UPDATE global_variables SET variable_value='monitor' 
WHERE variable_name='mysql-monitor_username';

UPDATE global_variables SET variable_value='Monitor123!' 
WHERE variable_name='mysql-monitor_password';

3.3. 配置后端 MySQL 服务器

根据你的双主双从架构添加服务器。我们设定主服务器的hostgroup_id=10,从服务器的hostgroup_id=20。需要将服务器的信息在管理界面中写入到mysql_servers表中

INSERT INTO mysql_servers(hostgroup_id, hostname, port, weight, comment) VALUES
(10, '192.168.4.50', 3306, 1000, 'Master1 - Write'),
(10, '192.168.4.51', 3306, 1000, 'Master2 - Write');

INSERT INTO mysql_servers(hostgroup_id, hostname, port, weight, comment) VALUES
(20, '192.168.4.52', 3306, 100, 'Slave1 - Read'),
(20, '192.168.4.53', 3306, 100, 'Slave2 - Read');

3.4.配置Mysql用户(用于应用连接)

首先,在 MySQL 主服务器 上创建应用用户。创建的这个用户是用于外部来查询的代理用户。可以按需求配置。

GRANT ALL PRIVILEGES ON *.* TO 'app_user'@'%' IDENTIFIED BY 'AppUser123!';
FLUSH PRIVILEGES;

然后在 ProxySQL管理单元中配置这个用户:

INSERT INTO mysql_users(username, password, default_hostgroup, transaction_persistent, comment) 
VALUES ('app_user', 'AppUser123!', 10, 1, 'Application user');

3.5.配置读写分离规则

这里需要按照之前定义的组修改,将相应的请求分发到相应的组(写到主服务器(写组),读到从服务器(从组))

INSERT INTO mysql_query_rules (rule_id, active, match_pattern, destination_hostgroup, apply, comment) VALUES
(1, 1, '^SELECT.*FOR UPDATE', 10, 1, 'Write SELECT'),        -- SELECT FOR UPDATE 路由到写组
(2, 1, '^SELECT', 20, 1, 'Read SELECT'),                     -- 普通 SELECT 路由到读组
(3, 1, '.*', 10, 1, 'All other to Write');                   -- 其他所有语句路由到写组

3.6.保存配置

LOAD MYSQL VARIABLES TO RUNTIME;

LOAD MYSQL SERVERS TO RUNTIME;

LOAD MYSQL QUERY RULES TO RUNTIME;

LOAD MYSQL USERS TO RUNTIME;

SAVE MYSQL VARIABLES TO DISK;

SAVE MYSQL SERVERS TO DISK;

SAVE MYSQL QUERY RULES TO DISK;

SAVE MYSQL USERS TO DISK;

LOAD MYSQL *** TO RUNTIME;

SAVE MYSQL *** TO DISK;

可以让配置立即生效,每一步都是持久化操作,并便于定位问题所在(当然运行的话只要复制后全部在管理界面粘贴就行)

4.测试

4.1.检查服务器状态

SELECT hostgroup_id, hostname, port, status, weight, comment 
FROM runtime_mysql_servers 
ORDER BY hostgroup_id, hostname;

正常输出应该显示所有服务器的 status 为 ONLINE(配置的时候有一台服务器坏了,重新配了一台)

4.2.检查连接监控

SELECT *
FROM monitor.mysql_server_ping_log 
ORDER BY time_start_us DESC 
LIMIT 10;

4.3测试应用连接

在客户端使用应用用户连接 ProxySQL 的代理端口(6033)

mysql -u app_user -pAppUser123! -h 服务器位置 -P 6033

SHOW DATABASES;

连接后可以进行测试查询

读写也正常

现在,可以直接连接proxySQL 服务器的6033端口,来实现读写分离、均衡负载地,对数据库进行访问

更多推荐