首先要明确核心结论:Mycat 不负责实现主从复制,仅依赖 MySQL 自身的主从复制机制,再通过 Mycat 配置将读请求转发到从库、写请求转发到主库(即读写分离)。
之前的对话中已经提到:Mycat 是数据库中间件,作用是「请求路由」,而非「数据同步」。数据同步(主从复制)的核心是 MySQL 自身的功能,Mycat 只需要感知主从节点的存在,就能实现读写分离。
因此,你问的「Mycat 中配置主从复制」,本质是 「先搭建 MySQL 主从复制(数据同步),再在 Mycat 中配置主从节点关联(请求路由)」 。以下是完整的分步实操(基于 CentOS 环境,MySQL 8.0 + Mycat 1.6.x):
一、核心前提:先搭建 MySQL 主从复制(数据同步核心)
Mycat 读写分离的基础是「主从数据一致」,必须先让 MySQL 主库和从库完成数据同步,Mycat 仅负责转发请求。
环境准备
- 主库(Master):IP
192.168.1.101,MySQL 8.0,数据库db1 - 从库(Slave):IP
192.168.1.103,MySQL 8.0,数据库db1(需手动创建,与主库同名) - 主从库网络互通,关闭防火墙或开放 3306 端口(MySQL 通信端口)
步骤 1:配置主库(Master)
1. 编辑 MySQL 配置文件
bash
运行
# CentOS 8+ 编辑 MySQL 配置(不同系统路径可能为 /etc/my.cnf)
vim /etc/my.cnf.d/mysql-server.cnf
在
[mysqld] 节点下添加以下配置(开启二进制日志,指定主库唯一 ID):ini
[mysqld]
server-id = 101 # 主库唯一 ID(1-2^32-1,不能与从库重复)
log-bin = mysql-bin # 开启二进制日志(主从复制的核心,记录所有写操作)
binlog-do-db = db1 # 仅同步 db1 数据库(按需配置,不写则同步所有库)
binlog-ignore-db = mysql # 忽略同步系统库(可选)
expire_logs_days = 7 # 二进制日志保留 7 天(避免占用磁盘)
2. 重启主库并验证配置
bash
运行
# 重启 MySQL 服务
systemctl restart mysqld
# 登录主库 MySQL,验证配置是否生效
mysql -uroot -p
mysql> show variables like 'server_id'; # 结果应为 101
mysql> show variables like 'log_bin'; # 结果应为 ON
3. 主库创建复制用户并授权
从库需要通过该用户连接主库同步数据:
sql
-- 主库执行(创建复制用户 repl,允许从库访问)
CREATE USER 'repl'@'192.168.1.103' IDENTIFIED BY 'Repl123!'; # 仅允许从库 IP 连接
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.1.103'; # 授予复制权限
FLUSH PRIVILEGES; # 刷新权限
-- 查看主库状态(记录 File 和 Position 值,从库配置需用)
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 156 | db1 | mysql | |
+------------------+----------+--------------+------------------+-------------------+
- 注意:记录
File(如mysql-bin.000001)和Position(如156),后续从库配置需要用到。
步骤 2:配置从库(Slave)
1. 编辑 MySQL 配置文件
bash
运行
vim /etc/my.cnf.d/mysql-server.cnf
在
[mysqld] 节点下添加以下配置(指定从库唯一 ID,开启中继日志):ini
[mysqld]
server-id = 103 # 从库唯一 ID(与主库不同)
relay-log = relay-bin # 开启中继日志(从库同步主库日志的临时文件)
replicate-do-db = db1 # 仅同步 db1 数据库(与主库一致)
replicate-ignore-db = mysql # 忽略同步系统库(可选)
read_only = 1 # 从库设为只读(避免直接写从库,root 用户除外)
2. 重启从库并验证配置
bash
运行
systemctl restart mysqld
# 登录从库 MySQL,验证配置
mysql -uroot -p
mysql> show variables like 'server_id'; # 结果应为 103
mysql> show variables like 'relay_log'; # 结果应为 ON
3. 从库配置主库信息并启动同步
sql
-- 从库执行(停止之前的同步进程,首次配置可跳过)
mysql> stop slave;
-- 配置主库信息(替换为实际主库 IP、复制用户、日志文件和位置)
mysql> change master to
master_host='192.168.1.101', # 主库 IP
master_user='repl', # 主库创建的复制用户
master_password='Repl123!', # 复制用户密码
master_log_file='mysql-bin.000001', # 主库 show master status 中的 File
master_log_pos=156; # 主库 show master status 中的 Position
-- 启动从库同步
mysql> start slave;
-- 验证主从同步状态(核心:Slave_IO_Running 和 Slave_SQL_Running 均为 Yes)
mysql> show slave status\G;
- 关键验证项:
Slave_IO_Running: Yes(从库 IO 线程正常,能连接主库并读取二进制日志)Slave_SQL_Running: Yes(从库 SQL 线程正常,能执行中继日志中的 SQL)
- 若为 No,查看
Last_IO_Error或Last_SQL_Error字段排查原因(如密码错误、日志文件 / 位置错误、主从数据不一致)。
4. 验证主从复制效果
在主库
db1 中创建表并插入数据,查看从库是否同步:sql
-- 主库执行(创建表 + 插入数据)
use db1;
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO user (id, name, age) VALUES (1, '张三', 20);
-- 从库执行(查询数据,确认同步成功)
use db1;
select * from user; # 应能看到 id=1 的「张三」记录
二、Mycat 配置:关联主从节点(实现读写分离)
MySQL 主从复制搭建完成后,Mycat 只需配置「主库(写节点)」和「从库(读节点)」,即可实现读写分离(写请求走主库,读请求走从库)。
步骤 1:修改 Mycat 核心配置文件(schema.xml)
bash
运行
vim /usr/local/mycat/conf/schema.xml
配置逻辑库、分片、主从节点关联,核心是
balance="1"(开启读写分离)和 readHost(关联从库):xml
<?xml version="1.0" encoding="UTF-8"?>
<mycat:schema xmlns:mycat="http://io.mycat/">
<!-- 逻辑库:应用连接的虚拟库 -->
<schema name="mycat_db" checkSQLschema="false" sqlMaxLimit="100">
<!-- 逻辑表:关联到主从库所在的分片 dn1 -->
<table name="user" dataNode="dn1" primaryKey="id" />
</schema>
<!-- 分片:对应真实数据库(主从库的 db1) -->
<dataNode name="dn1" dataHost="host1" database="db1" />
<!-- 主从节点配置(核心) -->
<dataHost name="host1"
maxCon="1000" minCon="10"
balance="1" <!-- 开启读写分离:读请求转发到从库 -->
writeType="0" <!-- 写请求转发到第一个可用的 writeHost(主库) -->
dbType="mysql" dbDriver="native">
<!-- 心跳检测:确保数据库存活 -->
<heartbeat>select 1</heartbeat>
<!-- 主库配置(writeHost:负责写请求) -->
<writeHost host="master-101"
url="192.168.1.101:3306"
user="mycat" <!-- Mycat 连接主库的用户(之前创建的 mycat/123456) -->
password="123456">
<!-- 从库配置(readHost:负责读请求,关联到父 writeHost) -->
<readHost host="slave-103"
url="192.168.1.103:3306"
user="mycat" <!-- Mycat 连接从库的用户(需在从库授权) -->
password="123456" />
</writeHost>
</dataHost>
</mycat:schema>
步骤 2:从库授权 Mycat 访问
Mycat 需要连接从库执行读请求,需在从库创建 Mycat 连接用户并授权:
sql
-- 从库执行(授权 Mycat 连接)
GRANT ALL ON *.* TO 'mycat'@'%' IDENTIFIED BY '123456';
FLUSH PRIVILEGES;
步骤 3:重启 Mycat 并验证
bash
运行
# 停止 Mycat(若已启动)
/usr/local/mycat/bin/mycat stop
# 前台启动 Mycat(查看日志,确认无报错)
/usr/local/mycat/bin/mycat console
- 启动成功标志:日志中出现
Mycat Server startup successfully。
三、验证 Mycat 读写分离效果
步骤 1:连接 Mycat 执行读写操作
bash
运行
# 用 MySQL 客户端连接 Mycat(8066 端口)
mysql -h127.0.0.1 -umycat_app -p123456 -P8066
# 切换到逻辑库
use mycat_db;
# 1. 写操作(INSERT:Mycat 转发到主库)
INSERT INTO user (id, name, age) VALUES (2, '李四', 22);
# 2. 读操作(SELECT:Mycat 转发到从库)
SELECT * FROM user;
步骤 2:确认请求分发正确
1. 验证写请求走主库
登录主库,查看 MySQL 日志,确认有 INSERT 操作:
sql
-- 主库执行(开启通用日志,临时查看)
set global general_log = on;
set global log_output = 'table'; # 日志写入 mysql.general_log 表
-- 查询写操作日志
select * from mysql.general_log where argument like '%INSERT INTO user%';
- 结果:能看到 Mycat 转发的 INSERT 请求(用户为
mycat_app)。
2. 验证读请求走从库
登录从库,查看日志,确认有 SELECT 操作:
sql
-- 从库执行(开启通用日志)
set global general_log = on;
set global log_output = 'table';
-- 查询读操作日志
select * from mysql.general_log where argument like '%SELECT * FROM user%';
- 结果:能看到 Mycat 转发的 SELECT 请求(主库日志无该 SELECT 记录)。
3. 验证数据一致性
从库执行查询,确认主库的 INSERT 数据已同步:
sql
-- 从库执行
use db1;
select * from user; # 应能看到 id=2 的「李四」记录(主从复制生效)
四、常见问题排查
1. MySQL 主从同步失败(Slave_IO_Running=No)
- 原因:主库 IP / 端口错误、复制用户密码错误、主库防火墙未开放 3306 端口。
- 解决方案:
- 验证从库能否 ping 通主库:
ping 192.168.1.101。 - 验证从库能否连接主库复制用户:
mysql -urepl -pRepl123! -h192.168.1.101 -P3306。 - 主库开放 3306 端口:
firewall-cmd --permanent --add-port=3306/tcp && firewall-cmd --reload。
- 验证从库能否 ping 通主库:
2. MySQL 主从同步失败(Slave_SQL_Running=No)
- 原因:主从库数据不一致(如主库已存在表,从库无)、SQL 语法不兼容。
- 解决方案:
- 备份主库
db1并导入从库:mysqldump -uroot -p db1 > db1.sql(主库),mysql -uroot -p db1 < db1.sql(从库)。 - 从库执行
stop slave; reset slave;后,重新执行change master to ...配置。
- 备份主库
3. Mycat 读请求仍走主库
- 原因:
schema.xml中balance参数配置错误(如balance="0",未开启读写分离)。 - 解决方案:确认
balance="1"(读请求转发到从库),重启 Mycat。
4. Mycat 连接从库失败
- 原因:从库未授权 Mycat 用户、从库 3306 端口未开放、从库 MySQL 未启动。
- 解决方案:
- 从库重新授权 Mycat 用户:
GRANT ALL ON *.* TO 'mycat'@'%' IDENTIFIED BY '123456';。 - 开放从库 3306 端口:
firewall-cmd --permanent --add-port=3306/tcp && firewall-cmd --reload。
- 从库重新授权 Mycat 用户:
核心总结
- Mycat 不实现主从复制,仅依赖 MySQL 自身的主从复制保证数据一致,Mycat 负责「请求路由」(写主读从)。
- 配置流程:先搭 MySQL 主从复制(数据同步)→ 再配置 Mycat 关联主从节点(读写分离)。
- 关键验证点:MySQL 主从同步状态(两个 Yes)、Mycat 读写请求分发正确(写主读从)。
按照以上步骤,即可完成「MySQL 主从复制 + Mycat 读写分离」的完整配置,实现系统并发能力提升~