MySQL复制之异步复制

记录备忘。

参考博文:https://blog.csdn.net/wzy0623/article/details/90081518


目录

一、概述

二、binlog简介

三、刷盘方式

四、复制流程

五、实验

5.1 环境规划

5.2 mysql安装

5.3 配置复制

5.3.1 停机

5.3.2 联机


一、概述

简单说,复制就是将一个MySQL数据库服务器(主库)的数据复制到一个或多个MySQL数据库服务器(从库)。复制的桥梁就是二进制日志。

复制给主库增加的开销主要体现在启用二进制日志带来的I/O,但是开销并不大,MySQL官方文档中称开启二进制日志会产生1%的性能损耗。出于对历史事务备份以及从介质失败中恢复的目的,这点开销是非常必要的。除此之外,每个从库也会对主库产生一些负载,例如网络和I/O开销。当从库读取主库的二进制日志时,可能会造成一定的I/O开销。如果从一个主库上复制到多个从库,唤醒多个复制线程发送二进制日志内容的开销将会累加。但所有这些复制带来的额外开销相对于应用对MySQL服务器造成的高负载来说是很小的。

 

二、binlog简介

二进制日志包含描述数据库更改的事件,如建表操作或对表数据的更改等。通过设置log-bin系统变量开启二进制日志,MySQL 8中缺省是开启的。

二进制日志有STATEMENT、ROW、MIXED三种格式,通过binlog-format系统变量设置:

  • STATMENT
    基于SQL语句的复制(statement-based replication,SBR)。每一条会修改数据的SQL语句会记录到binlog中。
    优点:不需要记录每行的数据变化,这样二进制日志会比较少,减少磁盘I/O,提高性能。
    缺点:在某些情况下会导致主库与从库中的数据不一致,例如last_insert_id()、now()等非确定性函数,以及用户自定义函数(user-defined functions,udf)等易出现问题。
  • ROW
    基于行的复制(row-based replication,RBR)。不记录每一条SQL语句的上下文信息,仅需记录哪条数据被修改了,修改成了什么样子,能清楚记录每一行数据的修改细节。
    优点:不会出现某些特定情况下的存储过程、函数或触发器的调用和触发无法被正确复制的问题。
    缺点:缺点是通常会产生大量的日志,尤其像大表上执行alter table操作时候会让日志暴涨。
  • MIXED
    混合复制(mixed-based replication,MBR)。是语句和行两种格式的混合使用,默认使用STATEMENT模式保存二进制日志,对于STATEMENT模式无法正确复制的操作,会自动切换到基于行的格式,MySQL会根据执行的SQL语句选择日志保存方式。MySQL 8 之前的默认格式。

 

二进制日志的存放位置最好设置到与MySQL数据目录不同的磁盘分区,以降低磁盘I/O的竞争,提升性能,并且在数据磁盘故障的时候还可以利用备份和二进制日志恢复数据

 

三、刷盘方式

主从数据是否一致还与重做日志和二进制日志的写盘方式有关。innodb_flush_log_at_trx_commit和sync_binlog系统变量分别控制两者的落盘策略

  • innodb_flush_log_at_trx_commit

        控制事物提交是否刷盘,有0、1、2三个可选值。
        0:表示每秒进行一次刷新,但是每次事务提交不进行任何操作
        1:表示每次事务提交都会进行刷新,这是最安全的模式
        2:表示每秒刷新,每次事务提交时不刷新,而是调用write将重做日志缓冲区里面的内容刷到操作系统页面缓存

从数据安全性和性能比较三种策略的优劣为:0表示每秒刷新,每次事务提交不进行任何操作,所以MySQL或操作系统崩溃时最多丢失一秒的事务。1由于每次事务提交都会是重做日志落盘,所以是最安全的,但是由于fsync的次数增多导致性能下降比较严重。2相对于0来说了多了每次事务提交时的一个write操作,此时数据虽然没有落磁,但是只要没有操作系统崩溃,即使MySQL崩溃,那么事务也是不会丢失的。

  • sync_binlog

MySQL在提交事务时调用MYSQL_LOG::write完成写二进制日志,并根据sync_binlog决定是否进行刷盘。
        0:由系统决定什么时候刷
        1:每提交一次事务,写一次binlog,并使用fdatasync()同步到硬盘
        n:每提交一次事务,写一次binlog,达到sync_binlog 设定的值后,调用fdatasync()同步到硬盘

sync_binlog=N和innodb_flush_log_at_trx_commit=N推荐配置组合

N=1,1

适合数据安全性要求非常高,而且磁盘IO写能力足够支持业务,比如充值消费系统

N=1,0

适合数据安全性要求高,磁盘IO写能力支持业务不富余,允许备库落后或无复制 

N=2,0或2,m(0<m<100)

适合数据安全性有要求,允许丢失一点事务日志,复制架构的延迟也能接受

N=0,0

磁盘IO写能力有限,无复制或允许复制延迟稍微长点能接受,例如:日志性登记业务

当两个参数设置为双1的时候,写入性能最差,当俩个参数设置为N(N>1 ),M(0<M<100)时,MySQL的写操作才能达到最高性能

 

四、复制流程

总的来说,MySQL复制有五个步骤:

  • 在主库上把数据更改事件记录到二进制日志中
        MySQL会按事务提交的顺序而非每条语句的执行顺序来记录二进制日志。在记录二进制日志后,主库会告诉存储引擎可以提交事务了。
  • 从库上的I/O线程向主库询问二进制日志中的事件
        从库会启动一个工作线程,称为I/O线程,I/O线程跟主库建立一个普通的客户端连接
  • 主库上的binlog dump线程向I/O线程发送二进制事件
        主库上启动一个特殊的二进制日志转储(binlog dump)线程,它会读取主库上二进制日志中的事件,但不会对事件进行轮询。如果从库追赶上了主库,它将进入睡眠状态,直到主库发送信号通知其有新的事件时才会被唤醒。
  • 从库上的I/O线程将二进制日志事件复制到自己的中继日志中
        从库I/O线程会将接收到的事件记录到中继日志中
  • 从库上的SQL线程读取中继日志中的事件,并将其重放到从库上
        SQL线程执行最后一步,该线程从中继日志中读取事件并在从库上执行。当SQL线程追赶I/O线程时,中继日志通常已经在系统缓存中,所以重放中继日志的开销很低。

 

五、实验

5.1 环境规划

  • 虚拟服务器
IP角色
192.168.56.11
192.168.56.12
  • 软件
软件名称

软件版本

OSCentOS Linux release 7.3.1611 (Core)
MySQLmysql-8.0.21
  • 路径
路径用途
/home/mysql/mysql8MySQL主目录
/home/mysql/mysql8/dataMySQL数据目录
/home/mysql/mysql8/logs/binlogMySQL二进制日志目录
/home/mysql/mysql8/logs/relaylogMySQL中继日志目录

5.2 mysql安装

参考 “MySQL安装脚本

 主库上建立复制专属用户(主库)

-- 主库执行SQL
create user 'repl'@'192.168.56.%' identified with mysql_native_password by '123456';
grant replication client,replication slave on *.* to 'repl'@'192.168.56.%';

5.3 配置复制

复制为异步复制,基于master_log_file和master_log_pos,只做整服务器级别的复制,不考虑对个别库表或使用过滤复制的情况。

5.3.1 停机

如果应用允许一定时间的脱机,这种场景下常用的做法是先直接将主库的数据目录整体拷贝到从库,再启动复制。具体步骤如下:

1、停掉复制涉及的实例(主、从库)

# 主从库都执行
/home/mysql/mysql8/bin/mysqladmin -uroot -p111111 -S/home/mysql/mysql8/logs/mysqld.sock shutdown

2、 将主库的数据目录复制到从库

# 从库执行,删除原文件否则主从关系建立会有问题
rm -fr /home/mysql/mysql8/data
rm -fr /home/mysql/mysql8/logs

# 主库执行,拷贝数据文件
scp -r /home/mysql/mysql8/data root@192.168.56.12:/home/mysql/mysql8/

# 主库执行,如果日志不在data文件夹下,需要吧binlog也拷贝过去
scp -r /home/mysql/mysql8/logs root@192.168.56.12:/home/mysql/mysql8/

# 从库执行,修改权限
chown mysql.mysql /home/mysql/mysql8/* -R

# 从库执行,注意!server_id和server_uuid不能重复,确保server_uuid不重复,删掉auto.cnf
rm -fr /home/mysql/mysql8/data/auto.cnf

3、启动所有实例(主、从)

# 主从库都执行
/home/mysql/mysql8/mysqld start

4、配置主从关系

-- 主库执行SQL,查看binlog信息。
show master status;

mysql> show master status;
+----------------+----------+--------------+------------------+-------------------+
| File           | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+----------------+----------+--------------+------------------+-------------------+
| bin-log.000006 |      156 |              |                  |                   |
+----------------+----------+--------------+------------------+-------------------+


-- 从库执行以下SQL,指向主库
CHANGE MASTER TO 
MASTER_HOST='192.168.56.11', 
MASTER_PORT=3308, 
MASTER_USER='repl', 
MASTER_PASSWORD='123456', 
MASTER_LOG_FILE='bin-log.000006', 
MASTER_LOG_POS=156;

5、查看主从关系是否正常(从库)

-- 从库执行SQL,查看主从关系
mysql> show slave status \G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
               ...............
                Connect_Retry: 60
              Master_Log_File: bin-log.000006    -- IO线程正在读取主库的binlog
          Read_Master_Log_Pos: 156               -- IO线程正在读取主库binlog的pos
               Relay_Log_File: relay-log.000002  -- 正在应用的本地应用中继日志
                Relay_Log_Pos: 322               -- 中继日志的位置
        Relay_Master_Log_File: bin-log.000006    -- SQL线程正在执行操作对应的master的binlog
             Slave_IO_Running: Yes               -- IO线程状态(No为停止,Yes运行)
            Slave_SQL_Running: Yes               -- SQL线程状态(No为停止,Yes运行)
            ..................                   -- 省略一些不重要状态
          Exec_Master_Log_Pos: 156               -- SQL线程正在执行操作对应的master的pos
          ....................                   -- 省略一些不重要状态
        Seconds_Behind_Master: 0                 -- 从库落后主库时间,单位秒
        ......................                   -- 省略一些不重要状态
1 row in set (0.00 sec)

另外在MySQL的日志中也有主从同步信息记录。

5.3.2 联机

大多数情况下是不允许停机的,配置复制被要求在不影响线上业务的情况下进行,而且还要求对线上库的影响越小越好。这种场景下有两种备选的复制方案:使用mysqldump程序或使用如XtraBackup的第三方工具。

这两种方案有各自的适用场合:

  • mysqldump:逻辑备份,恢复速度慢,适用于数据量小的库
        优点:无需额外安装,支持部分复制,replicate-do-table=db1.*用这种方法可以只复制db1库,忽略其它事件
        缺点:生成主库转储数据的SQL语句,占用空间,主要是恢复慢
  • xtrabackup:物理备份,适用于数据量大的库
        优点:支持在线热备份,物理备份备份和恢复速度快
        缺点:不支持部分复制,需要额外安装xtrabackup及依赖包

 

5.3.2.1 mysqldump方式

1、安装MySQL,见上文“5.2 MySQL安装

2、从库配置主库的信息(从库)

-- 从库执行SQL
CHANGE MASTER TO 
MASTER_HOST='192.168.56.11', 
MASTER_PORT=3308, 
MASTER_USER='repl', 
MASTER_PASSWORD='123456';

注意!在上面这条命令中并没有指定主库二进制文件的文件名和位置。

3、用mysqldump建立复制(从库)

# 从库执行
/home/mysql/mysql8/bin/mysqldump \
--single-transaction \
--all-databases \
--master-data=1 \
--host=192.168.56.11 \
--user=admin \
--password=admin \
--apply-slave-statements | \
/home/mysql/mysql8/bin/mysql -uroot -p111111 -S/home/mysql/mysql8/logs/mysqld.sock
  • --single-transaction
        对Innodb表执行非锁定导出。
  • --master-data
        转储输出包含 CHANGE MASTER TO MASTER_LOG_FILE='binlog.000004', MASTER_LOG_POS=1480的语句。
        如果选项值为2,则CHANGE MASTER TO语句将写为SQL注释,因此仅提供信息,不会执行。
        如果参数值为1,则该语句不会写为注释,并在重新加载转储文件时执行。
        如果未指定选项值,则默认值为1。
  • --apply-slave-statements
        转储输出包含STOP SLAVE语句,在输出结尾处添加START SLAVE语句,自动开启复制。
  • 通过管道操作符,导出导入一步进行,不需要中间落盘生成文件

4、确认复制状态,见上文“5.3.1 停机”中的第5步

5.3.2.2 xtrabackup方式

1、安装MySQL,见上文“5.2 MySQL安装

2、安装xtrabackup(主、从)

# 主库从库都执行

# 下载xtrabackup
cd /usr/local/src
curl -O https://www.percona.com/downloads/Percona-XtraBackup-LATEST/Percona-XtraBackup-8.0.14/binary/redhat/7/x86_64/percona-xtrabackup-80-8.0.14-1.el7.x86_64.rpm

# 安装
yum -y install \
perl \
perl-devel \
libaio \
libaio-devel \
perl-Time-HiRes \
perl-DBD-MySQL\
perl-Digest-MD5 \
perl-DBI \
percona-xtrabackup-80-8.0.14-1.el7.x86_64.rpm

3、主库导出备份

# 主库执行

# 主库xtrabackup备份
xtrabackup -uadmin -padmin --socket=/home/mysql/mysql8/logs/mysqld.sock \
--no-lock --backup --compress --compress-threads=4 \
--target-dir=/home/mysql/mysql8/backup

# 复制到从库
scp -r /home/mysql/mysql8/backup root@192.168.56.12:/home/mysql/mysql8/

注意! MySQL用户的密码认证方式是mysql_native_password。MySQL8默认认证方式报错

4、从库解压并恢复

# 从库执行

# 解压备份需要安装qpress,如果验证不通过执行下 yum update percona-release
yum -y install https://www.percona.com/redir/downloads/percona-release/redhat/1.0-24/percona-release-1.0-24.noarch.rpm
yum -y install  qpress

# 解压备份
rm -fr /home/mysql/mysql8/data
mv /home/mysql/mysql8/backup /home/mysql/mysql8/data
xtrabackup --decompress --parallel=4 --remove-original --target-dir=/home/mysql/mysql8/data

# 准备备份
xtrabackup --prepare --target-dir=/home/mysql/mysql8/data

# 启动MySQL
chown mysql.mysql /home/mysql/mysql8/* -R

4、配置复制

查看备份中xtrabackup_binlog_info文件,其中记录了binlog-file和binlog-pos

# 从库执行

cat /home/mysql/mysql8/data/xtrabackup_binlog_info

执行命令向主库

-- 从库执行
CHANGE MASTER TO 
MASTER_HOST='192.168.56.11', 
MASTER_PORT=3308, 
MASTER_USER='repl', 
MASTER_PASSWORD='123456', 
MASTER_LOG_FILE='bin-log.000021', 
MASTER_LOG_POS=156;

5、确认复制状态,见上文“5.3.1 停机”中的第5步

 

异步复制的几种搭建方式记录完成。

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值