MySQL主从复制基于MySQL官方提供的MySQL Replication技术,实现了数据从一个主服务器向一个或多个从服务器的同步。主从复制不仅是一种备份方式,更为MySQL高可用提供了数据同步的基础。
1、MySQL Replication原理
在MySQL Replication中,主服务器称为Master,从服务器称为Slave。Slave会从Master上拉取MySQL的二进制日志文件(Binary Log),然后将该日志解析为SQL语句并完全顺序的执行这些SQL语句以达到与Master上执行同样的SQL的效果,保证数据的一致性。
整个过程具体如下:
- Slave上起一个IO线程,连接Master,然后请求从指定位置开始的Binary Log内容
- Master在接收请求之后读取指定位置开始的Binary Log内容并通过自身的IO线程返回给Slave的IO线程,返回的信息不仅包括Binary Log日志中的内容,还包括Binary Log日志的名称和这些信息在Binary Log中的位置
- Slave在接收到信息后,将获取到的Binary Log内容写入Relay Log中(名为mysql-relay-bin.xxx的文件),并将Binary Log的文件名和这些信息在Binary Log中的位置记录到名为master-info的文件中
- Slave的SQL线程在监测到Relay Log的更新后会马上解析Relay Log并生成SQL语句,然后执行这些SQL语句。至此,整个主从复制过程结束
虽然MySQL Replication是异步的,但其性能非常高效,延时非常小。同时MySQL Replication支持链式复制,即Slave下还可以再链接Slave,Slave也可以充当Master的角色。
注意:Slave会从Master上拉取Binary Log,所以在Master上必须开启MySQL的Binary Log功能。
注意:在MySQL Replication中,只能在Master上更新数据库的数据,Slave只提供查询操作。
2、MySQL Replication数据复制方式和常用架构
2.1、数据复制方式
MySQL Replication支持多种类型的数据复制方式,常见的有一下三种方式:
- 基于语句的复制:默认采用的方式,效率非常高。是将在Master上执行的SQL语句在Slave上重新执行一次。一旦MySQL发现无法进行精确复制时,会自动选择基于行的复制
- 基于行的复制:将Master上改变的内容复制到Slave,而不是执行SQL语句。MySQL 5.0版本起开始支持基于行的复制
- 混合类型的复制:基于以上两种复制方式,一旦发现基于语句的复制无法精确完成,就会采用基于行的复制
2.2、主从复制的常用架构
MySQL Replication常见的实现架构有以下几种:
- 一主一从:即一个Master和一个Slave,是最常见的架构
- 一主多从:即一个Master和多个Slave。经常用在写操作不频繁,查询量比较大的业务环境
- 主主互备:双主互备,两个MySQL相互将对方做为自己的Master,自己同时又是对方的Slave。主要用于对MySQL写操作要求比较高的环境中,避免MySQL的单点故障
- 双主多从:在双主互备的基础上再加上多个Slave。主要用于MySQL写操作要求较高,同时查询量比较大的环境中
MySQL Replication必须遵从以下原则:
- 同一时刻只能有一个Master进行写操作
- 每台MySQL要确保各自的Server ID唯一
- 一个Slave可以将从Master获取的信息传递给其他的Slave
- 必须保证MySQL版本的一致
3、MySQL Replication一主一从架构的实现
这里通过一个例子来演示如何配置MySQL以实现一主一从的主从复制架构。
实验环境:
- DB1:操作系统CentOS 7.6.1810,IP地址192.168.0.110,MySQL版本5.7.25
- DB2:操作系统CentOS 7.6.1810,IP地址192.168.0.88,MySQL版本5.7.25
配置DB1为Master,DB2为Slave。
1、配置DB1和DB2的/etc/my.cnf
在DB1上的/etc/my.cnf中添加以下内容:
# 在[mysqld]下添加以下内容 server-id=110 log-bin=mysql-bin replicate-wild-ignore-table=mysql.% replicate-wild-ignore-table=information_schema.%
- server-id:设置MySQL的Server ID,自行指定,只要两台MySQL不同即可
- log-bin:开启MySQL的Binary Log并设置Binary Log文件名的前缀,这样会生成类似mysql-bin.000001的日志文件
- replicate-wild-ignore-table:复制过滤选项,用于排除不需要复制的数据库和表,%表示指定数据库的所有表;另有一个replicate_wild_do_table选项,用于指定需要复制的数据库和表
在DB2上的/etc/my.cnf中添加以下内容:
# 在[mysqld]下添加以下内容 server-id=88 read-only=1 log-bin=mysql-bin relay-log=mysql-relay-bin replicate-wild-ignore-table=mysql.% replicate-wild-ignore-table=information_schema.%
- read-only:设置MySQL只读
- relay-log:开启Slave上的Relay Log并设置Relay Log文件名的前缀
2、手动同步数据库
如果DB1上已经有数据库存在,则必须将这些库同步到DB2上。线上环境可以给MySQL加锁以阻止写入,或者停止MySQL服务。
这里通过加锁的方式阻止数据写入,在MySQL交互模式使用以下命令加锁:
mysql> flush tables with read lock;
注意:此时不要关闭这个终端,关闭终端会导致锁失效,另外打开一个终端以进行下一步的操作。
打包位于/db下的MySQL数据文件目录mysql:
[root@localhost db]# tar -zcvf mysql.tar.gz mysql
将这个压缩包通过scp发送到DB2上:
[root@localhost db]# scp mysql.tar.gz root@192.168.0.88:/db
将压缩包解压并覆盖DB2上的MySQL数据存储目录。然后依次重启DB1和DB2。
关于server-uuid的问题
在将BD1上的MySQL存储目录应用到DB2时,可能会产生因为server-uuid相同而导致DB2的MySQL无法启动的问题。这里可以通过删除DB2上MySQL数据存储目录下的auto.cnf文件解决,该文件删除后启动MySQL时会重新生成。
3、在DB1上创建复制用户
在DB1上创建专门的用户用于DB2复制Binary Log,该用户必须有从DB2登录的权限:
mysql> grant replication slave on *.* to 'repl'@'192.168.0.88' identified by '123456';
4、查看DB1上的Binary Log文件名和Position值
在DB1上通过以下命令查看需要的内容:
mysql> show master status;
显示如下内容:
+------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000001 | 448 | | | | +------------------+----------+--------------+------------------+-------------------+
这里记录下File栏和Position栏的内容,以便DB2使用。
5、DB2上将DB1设置为Master并开启Slave
在DB2上使用以下命令将DB1设置为自己的Master:
mysql> change master to master_host='192.168.0.110',master_user='repl',master_password='123456',master_log_file='mysql-bin.000001',master_log_pos=448;
使用以下命令在DB2上开启Slave:
mysql> start slave;
执行以下命令查看Slave运行状态:
mysql> show slave statusG
显示的信息如下:
*************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.0.110 Master_User: repl Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000001 Read_Master_Log_Pos: 900 Relay_Log_File: mysql-relay-bin.000002 Relay_Log_Pos: 320 Relay_Master_Log_File: mysql-bin.000001 Slave_IO_Running: Yes Slave_SQL_Running: Yes
只要Slave_IO_Running和Slave_SQL_Running显示的是Yes,就说明Slave正常运行。至此,MySQL的主从复制配置完毕。