ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

mysql集群

mysql集群

背景:几台centos7.9机器,ip网段是192.168.2.*,mysql8.0.27,firewalld互相之间已经放通3306

一、一主一从

背景:192.168.2.7是主,192.168.2.8是从

1.0 主从服务器必须时间同步-主和从

yum install chrony -y systemctl enable chronyd --now

1.1 修改配置文件-主

vim /etc/my.cnf

log_bin=master1-bin
server-id=1
binlog_format=ROW

systemctl restart mysqld

1.2 创建用于从库复制的用户,并赋予权限-主

# 创建新用户 rep,让集群192.168.2.的都可以访问 CREATE USER rep@'192.168.2.%' IDENTIFIED WITH mysql_native_password BY '新密码.'; #赋予权限 grant replication slave, replication client on *.* to rep@'192.168.2.%';

注:

  1. replication slave是复制必须权限
  2. replication client用于查看master状态
  3. 主从账号建议使用密码插件:mysql_native_password,使用caching_sha2_password 有可能因多环节中有旧版本的不支持,引发2061问题。
    检查密码插件:

select user,host,plugin from mysql.user where user=‘rep’;

修改密码插件

alter user rep@‘192.168.2.%’ identified with mysql_native_password by ‘密码.’;

1.3 备份全量数据,便于从库同步-主

# 备份 mysqldump -uroot -p --all-databases --single-transaction --source-data=2 --flush-logs --column-statistics=0 > /backup/2026-10-31/`date +%F-%H`-mysql-all.sql # 发送给从节点 scp /backup/2026-10-31/2026-10-31-15-mysql-all.sql root@192.168.2.8:/backup/2026-10-31/ # 记录日志标志点位置(找CHANGE MASTER TO MASTER_LOG_FILE,记录binlog文件名 和 pos) head -n 30 /backup/2026-10-31/2026-10-31-15-mysql-all.sql

注:

  1. 如:CHANGE MASTER TO MASTER_LOG_FILE=‘master1-bin.000002’, MASTER_LOG_POS=156;
  2. 记录 master1-bin.000002’ 和 156

1.4 从库测试主库rep用户是否可用-从

mysql -h 192.168.2.7 -urep -p # 正常登录就没问题,注:这个账号只有复制权限,无读写权限

1.5 修改配置-从

vim /etc/my.cnf

server-id=2
read_only=ON

systemctl restart mysqld

1.6 先导入主库全量备份文件-从

mysql -uroot -p < /backup/2026-10-31/2026-10-31-15-mysql-all.sql

1.7 在从库设置主服务器-从

change replication source to source_host='192.168.2.7', source_user='rep', source_password='rep用户密码', source_log_file='master1-bin.000002', source_log_pos=156;

注:

  1. source_host是主库,这里建议写主库ip,不要写hosts,容易出错
  2. source_user是在主库设置的复制权限账号
  3. source_password是复制权限账号的密码
  4. source_log_file和source_log_pos是在备份文件那记录的binlog日志文件名和标志点
  5. 如果使用的是caching_sha2_password,则要使用ssl,加上source_ssl=1
  6. mysql8.0.22之前是用change master to master_host,master_user,master_password,master_log_file,master_log_pos

1.8 启动从设备-从

start replica; #查看启动状态 show replica status\G;

注:

  1. Slave_IO_Running: Yes 从库io线程连接主库,拉取主库binlog,写入到从库的relay-log中继日志。
  2. Slave_SQL_Running: Yes 从库sql线程,读取本地relay-log中继日志,在从库回放sql
  3. 两个必须同时yes才算成功
  4. \G输出转向为竖向显示
  5. 旧版是start slave; show slave status\G,新版依旧兼容

1.9 注意事项

# 配置完主从后,需要修改主库信息(重新配置change replication source to ) # 要先停止从库 stop replica; # 清除从库在主库复制过来的所有信息 reset replica all;

二、 一主一从(gtid)

好处是不需要记录binlog日志分割点,可以让从库与主库自动协商。
背景:192.168.2.7是主,192.168.2.8是从

2.0 所有服务器同步时间

yum install chrony -y systemctl enable chronyd --now

2.1 修改配置文件-主

vim /etc/my.cnf

log_bin=master1-bin
server-id=1
binlog_format=ROW
gtid_mode=ON
enforce_gtid_consistency=1

systemctl restart mysqld

2.2 创建用于从库复制的用户,并赋予权限-主

# 创建新用户 rep,让集群192.168.2.的都可以访问 CREATE USER rep@'192.168.2.%' IDENTIFIED WITH mysql_native_password BY '新密码.'; #赋予权限 grant replication slave, replication client on *.* to rep@'192.168.2.%';

2.3 备份全量数据,便于从库同步-主

# 备份 mysqldump -uroot -p --all-databases --single-transaction --source-data=1 --flush-logs --column-statistics=0 > /backup/2026-10-31/`date +%F-%H`-mysql-all.sql # 发送给从节点 scp /backup/2026-10-31/2026-10-31-15-mysql-all.sql root@192.168.2.8:/backup/2026-10-31/

注:

  1. 不再需要看binlog分割点,所以配置source-data=1

2.4 从库测试主库rep用户是否可用-从

mysql -h 192.168.2.7 -urep -p # 正常登录就没问题,注:这个账号只有复制权限,无读写权限

2.5 修改配置-从

vim /etc/my.cnf

server-id=2
read_only=ON
gtid_mode=ON
enforce_gtid_consistency=1

systemctl restart mysqld

2.6 先导入主库全量备份文件-从

mysql -uroot -p < /backup/2026-10-31/2026-10-31-15-mysql-all.sql

2.7 在从库设置主服务器-从

change replication source to source_host='192.168.2.7', source_user='rep', source_password='rep用户密码', source_auto_position=1;

注:

  1. source_auto_position=1自动与主库商量binlog日志的分割标志位

2.8 启动从设备-从

start replica; #查看启动状态 show replica status\G;

注:

  1. Slave_IO_Running: Yes 和 Slave_SQL_Running: Yes 必须同时才算成功。

三、双主双从

双主是在一主一从的基础上配置为互为主从
然后两从库配置主库的信息
背景:192.168.2.7是主1,192.168.2.8是主2,192.168.2.9是从1,192.168.2.10是从2

3.0 所有服务器同步时间

yum install chrony -y systemctl enable chronyd --now

3.1 修改配置文件-主1

vim /etc/my.cnf

log_bin=master1-bin
server-id=1
binlog_format=ROW
gtid_mode=ON
enforce_gtid_consistency=1
auto-increment-increment=2
auto-increment-offset=1

systemctl restart mysqld

3.2 修改配置文件-主2

vim /etc/my.cnf

log_bin=master2-bin
server-id=2
binlog_format=ROW
gtid_mode=ON
enforce_gtid_consistency=1
auto-increment-increment=2
auto-increment-offset=2

systemctl restart mysqld

注:

  1. auto-increment-increment,auto-increment-offset,配置自增主键主1生成奇数,主2生成偶数,防止自增主键冲突。双主都同时写时,必须配置。
  2. 如果双主中,只写其中一台,另外一台作为备用,可以不配置auto-increment-increment,auto-increment-offset

3.3 创建用于从库复制的用户,并赋予权限-主1和主2

# 创建新用户 rep,让集群192.168.2.的都可以访问 CREATE USER rep@'192.168.2.%' IDENTIFIED WITH mysql_native_password BY '新密码.'; #赋予权限 grant replication slave, replication client on *.* to rep@'192.168.2.%';

3.4 双主互相测试rep用户是否可用-主1主2

mysql -h 192.168.2.8 -urep -p # 正常登录就没问题 mysql -h 192.168.2.7 -urep -p # 正常登录就没问题

3.5 先同步双主数据,备份全量数据-主1

# 备份 mysqldump -uroot -p --all-databases --single-transaction --source-data=1 --flush-logs --column-statistics=0 > /backup/2026-10-31/`date +%F-%H`-mysql-all.sql # 发送给主2节点 scp /backup/2026-10-31/2026-10-31-15-mysql-all.sql root@192.168.2.8:/backup/2026-10-31/

3.6 先导入主1全量备份文件-主2

mysql -uroot -p < /backup/2026-10-31/2026-10-31-15-mysql-all.sql

3.7 在主2设置主1服务器-主2

change replication source to source_host='192.168.2.7', source_user='rep', source_password='rep用户密码', source_auto_position=1;

3.8 启动主2为主1从设备-主2

start replica; #查看启动状态 show replica status\G;

注:

  1. Slave_IO_Running: Yes 和 Slave_SQL_Running: Yes 必须同时才算成功。

3.9 在主1设置主2服务器-主1

# 校验数据完成同步后再开始 change replication source to source_host='192.168.2.8', source_user='rep', source_password='rep用户密码', source_auto_position=1;

3.10 启动主1为主2从设备-主1

start replica; #查看启动状态 show replica status\G;

注:

  1. Slave_IO_Running: Yes 和 Slave_SQL_Running: Yes 必须同时才算成功。
  2. 可以开始校验双主间是否数据同步
  3. 至此双主配置成功

3.11 配置从1配置文件-从1

vim /etc/my.cnf

server-id=3
read_only=ON
gtid_mode=ON
enforce_gtid_consistency=1
master-info-repository=TABLE
relay-log-info-repository=TABLE

systemctl restart mysqld

注:

  1. 从机把主的信息存在主信息仓库里。主信息库可以是文件也可以上表,具体由–master-info-repository参数值决定。–master-info-repository=file时 会生成master.info 和 relay-log.info2个文件。
  2. 如果–master-info-repository=table,信息就会存在mysql.slave_master_info表中。–relay-log-info-repository=table写在mysql.slave_relay_log_info表中。

3.12 配置从2配置文件-从2

vim /etc/my.cnf

server-id=4
read_only=ON
gtid_mode=ON
enforce_gtid_consistency=1
master-info-repository=TABLE
relay-log-info-repository=TABLE

systemctl restart mysqld

3.13 导入数据-从1从2

# 在从1从2创建目录 mkdir -p /backup/2026-10-31/ # 主1/主2发送全量备份文件给从1节点 scp /backup/2026-10-31/2026-10-31-15-mysql-all.sql root@192.168.2.9:/backup/2026-10-31/ # 主1/主2发送全量备份文件给从2节点 scp /backup/2026-10-31/2026-10-31-15-mysql-all.sql root@192.168.2.10:/backup/2026-10-31/ # 从1从2导入数据 mysql -uroot -p < /backup/2026-10-31/2026-10-31-15-mysql-all.sql

3.14 设置主库-从1

# 配置主1 change replication source to source_host='192.168.2.7',source_user='rep',source_password='chaoROOT1314.',source_auto_position=1; #开启从服务器 start replica; # 查看 show replica status\G

3.15 设置主库-从2

# 配置主2 change replication source to source_host='192.168.2.8',source_user='rep',source_password='chaoROOT1314.',source_auto_position=1; #开启从服务器 start replica; # 查看 show replica status\G

注:

  1. 至此,双主双从已经配置完毕
  2. 双主同时写入的业务,有可能造成脑裂场景,建议配合MGR或keepalive使用。或者只要一主写入,另一主作为备库。

3.16 附加:从服务器多通道 --不建议(不建议从库配置多channel追两主库)

# 配置主1 change replication source to source_host='192.168.2.7',source_user='rep',source_password='chaoROOT1314.',source_auto_position=1 for channel 'master1'; # 配置主2 change replication source to source_host='192.168.2.8',source_user='rep',source_password='chaoROOT1314.',source_auto_position=1 for channel 'master2'; #开启从服务器 start replica for channel 'master1'; start replica for channel 'master2'; # 查看master1 show replica status for channel 'master1' \G # 查看master2 show replica status for channel 'master2' \G # 同时查看 show replica status;

注:

  1. start replica 会同时启动使用channel

3.17 附加

# 查看复制同步信息 show replica status\G # 查看主库binlog状态 show master status; # 查看GTID已执行集合 select @@gtid_executed; # 查看复制账号权限 show grants for rep@'192.168.2.%';

4. 附加经验

4.1 mysql集群出问题排查经验

# 查看状态 show replica status\G

  1. io线程没问题,sql线程出问题,代表依旧可以从主库获取binlog,数据不会丢失,只是sql线程执行中继日志relay_log时遇到一条有问题的sql卡住了
  2. 记录事务id:c9b3e42f-d4de-11f1-8295-000c29f59b92:4,到mysqld.log日志中查
# 根据事务id在日志中查询 less /var/log/mysqld.log

  1. 查到是在执行创建’mycatproxy2’@'192.168.2.11’卡住了,只需分析为什么这条sql失败,结合错误码:Error_code: MY-001396,大概率是因为这个用户已存在。可能原因是双主同时手动创建这个用户,等sql执行中继日志时,用户已存在创建失败。
# 在主1主2检查这个用户是否一致 SELECT user,host,plugin,authentication_string FROM mysql.user WHERE user='mycatproxy';
  1. 一致,则这条中继日志的sql就没有执行必要了,将这个事务跳过即可
  2. 如果不一致,则自己判断取舍,额外分析。
# 一致情况下 # 关闭复制 stop replica; # 跳过事务-提交空事务 set @@session.gtid_next='c9b3e42f-d4de-11f1-8295-000c29f59b92:4'; begin;commit; set @@session.gtid_next=AUTOMATIC; # 启动复制 start replica; show replica status\G

恢复正常

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进