概述

主从复制是指将主数据库的DDl(主要由create、alter、drop、truncate),DML操作通过二进制日志传到从库服务器中,然后在从库上面对这些日志重新执行,从而使得从库和主库的数据保持同步

MySQL 复制的有点主要包含以下三个方面:

  1. 主库出现问题可以快速切换到从库提供服务
  2. 实现读写分离,降低主库的访问压力
  3. 可以在从库中执行备份,以免备份期间影响主库服务

原理

从上图来看,复制分为三步:

  1. master主库在事务提交操作时,会把数据变更记录在二进制日志文件Binlog中
  2. 从库读取主库的二进制日志文件Binlog ,写入到从库的中继日志relany log
  3. slave重做中继日志中的事件,将改变反应它自己的数据。

搭建

master为主库

node为从库

主库master配置

  1. 开启binlog日志

在MySQL8.0版本之后默认开启binlog二进制日志,查看主库的binlog二进制日志是否开启

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mysql> show variables like '%log_bin%';
+---------------------------------+-------+
| Variable_name | Value |
+---------------------------------+-------+
| log_bin | OFF |
| log_bin_basename | |
| log_bin_index | |
| log_bin_trust_function_creators | OFF |
| log_bin_use_v1_row_events | OFF |
| sql_log_bin | ON |
+---------------------------------+-------+
6 rows in set (0.01 sec)

# 可以看到在5.7版本中并没有开启

修改mysql配置文件/etc/my.cnf

1
2
3
4
5
6
[mysqld]
log-bin=1 #开启logbin
log-bin=mysql-bin #指定文件名和路径,这里是默认路径
binlog-format=Row #文件类型

# 其实只加入 log-bin=mysql-bin 一行也可以
  1. 修改mysql文件/etc/my.cnf
1
2
3
4
5
6
7
8
9
10
# mysql服务ID,保证整个集群环境中唯一。
server-id=1
# 是否只读,1代表只读,0代表读写
read-only=0

# 可以不用设置,需要了解一下
# 忽略的数据,指不需要同步的数据库
# binlog-ignore-db=mysql
# 指定同步的数据库
# binlog-do-db=db01
  1. 登录mysql,创建远程连接的账号,拧授予主从复制权限
1
2
# 创建yyt用户并设置密码,使用户可以在任意主机连接该mysql服务并分配主从复制权限
grant replication slave on *.* to 'yyt'@'%' identified by 'Yyt000000';

扩展

主从同步账号需要如下这些权限:

replication slave

拥有此权限可以查看从服务器,从主服务器读取二进制日志。

replication client

拥有此权限可以查询master server、slave server状态。

如果想要在Slave上有权限执行 “LOAD TABLE FROM MASTER” 或 “LOAD DATA FROM MASTER” 语句的话,必须授予全局的 FILE 和 SELECT 权限:

a、select

必须有select的权限,才可以使用select table。

b、file

拥有file权限才可以执行 select ..into outfile和load data infile…操作,但是不要把file, process, super权限授予管理员以外的账号,这样存在严重的安全隐患。

  1. 通过指令,查看二进制日志坐标
1
2
3
4
5
6
show master status;

字段含义说明:
file:从哪个日志文件开始推送日志文件
position:从哪个位置开始推送日志
binlog_ignore_db:指定不需要同步的数据库

从库node配置

  1. 修改配置文件/etc/my.cnf
1
2
3
4
5
6
7
8
9
10
# mysql服务ID,保证整个集群环境中唯一。这里需要注意不能和主库ID一样
server-id=2
# 是否只读,1代表只读,0代表读写
read-only=1
# 对普通用户只读,管理员不受限制


# 扩展(了解即可,不需要设置)
# 设置管理员只读
super-read-only=1
  1. 重启mysql服务
1
systemctl restart mysqld
  1. 登录mysql,设置主库配置

image-20230328173205237

1
change master to master_host='10.0.0.102',master_user='yyt',master_password='Yyt000000';
  1. 开启同步操作

image-20230328173343810

1
2
start replica status; # 8.0.22之后 
start slave; # 8.0.22之前,之后都可以用
  1. 验证操作
1
2
show replica status\G # 8.0.22之后
show slave status\G # 8.0.22之前,之后都可以使用
  1. 查看

这里我遇到了一个错误,后面处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State:
Master_Host: 10.0.0.102
Master_User: yyt
Master_Port: 3306
Connect_Retry: 60
Master_Log_File:
Read_Master_Log_Pos: 4
Relay_Log_File: localhost-relay-bin.000002
Relay_Log_Pos: 4
Relay_Master_Log_File:
Slave_IO_Running: No
Slave_SQL_Running: Yes

错误解决

Slave_IO_Running: No # 负责与主机的io通信

Slave_SQL_Running: Yes # 负责自己的slave mysql进程。

找到my.cnf里面配置的mysql错误异常日志文件位置,log-error配置信息,我这里是/var/log/mariadb/mariadb.log

查看错误异常日志后发现

1
2023-03-28T10:16:46.124334Z 1 [ERROR] Slave I/O for channel '': Fatal error: The slave I/O thread stops because master and slave have equal MySQL server UUIDs; these UUIDs must be different for replication to work. Error_code: 1593

通过网上查询后发现是 由于uuid相同,而导致触发此异常,

原因:我的环境是vm虚拟机,克隆一台mysql虚拟机,mysql 有个uuid , 然而uuid 是唯一标识的,所以我克隆过来的uuid是一样的,只需要修改一下uuid 就可以了,找到auto.cnf 文件修改uuid

1
2
3
4
5
6
7
[root@localhost ~]# find / -iname "auto.cnf"
/soft/mysql-5.7.22-linux-glibc2.12-x86_64/data/auto.cnf

# 编辑这个配置文件,修改一位即可
# 重启mysqld服务
# stop slave;
# start slave;

发现问题已解决

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.0.0.102
Master_User: yyt
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000002
Read_Master_Log_Pos: 2007
Relay_Log_File: localhost-relay-bin.000008
Relay_Log_Pos: 320
Relay_Master_Log_File: mysql-bin.000002
Slave_IO_Running: Yes
Slave_SQL_Running: Yes

参考资料

mysql主从复制之异常解决— Slave_IO_Running: NO_gblfy的博客-CSDN博客