【分布式设计】MySQL复制是如何工作的​

"本文详细介绍了MySQL的主从复制机制,包括基于行和基于语句的复制方式,以及复制的三个步骤:主库记录二进制日志、从库复制并重放日志。还提供了一个实战配置示例,展示了如何在Docker环境下设置MySQL5.7的主从同步,包括创建数据同步用户、配置主从节点等步骤。最后,通过`show slave statusG`检查主从同步状态。"
摘要由CSDN通过智能技术生成

MySQL主从复制

在之前“复制”文章中提到过,复制解决的基本问题是让分布式服务器中的数据保持同步。主节点的数据可以同步到从节点上,同时当主节点发生故障时,从节点也可以被切换为主节点。

对于MySQL复制,支持基于行的复制和基于语句的复制方式。而这几种方式都是通过在主库上记录二进制日志、在备库重放日志的方式来实现异步的数据复制。

首先mysql复制是如何工作的呢?

总的来说,mysql复制有三个步骤:

  • 1.在主库上把数据更改记录到二进制日志(Binary Log,二进制日志事件)中;

在每次准备提交事务完成数据更新前,主库将数据更新的时间记录到二进制日志中。mysql会按照事务提交的顺序,而非每条语句的执行顺序来记录二进制日志。在记录二进制日志后,主库会告诉存储引擎可以提交事务。

  • 2.从库将主库上的日志复制到自己的中继日志(relay log)中;

首先,从库会启动一个工作线程-I/O线程,I/O线程与主库建立一个普通的客户端连接;
然后在主库上会启动一个二进制转储(binlog dump)线程,该二进制转储线程会读取主库的二进制日志中的事件,返回给从库I/O线程,从库I/O线程会将接收到的事件记录到中继日志中。

该二进制转储线程不会对事件进行轮询。当该线程追赶上主库时,它将进入睡眠状态,直到主库发送信号量通知其有新的事件产生时才会被唤醒。

  • 3.从库读取中继日志中的事件,并将其重放到从库数据之上。

从库的sql线程执行最后写入过程。该sql线程从中继日志中读取事件并在从库执行,从而实现从库数据的更新。

另外,可以通过配置选项来决定,在sql线程执行事件时,是否写入其自己的二进制日志中。

该复制架构实现了读取事件和重放事件的解耦,允许两个过程异步进行。I/O线程和重放sql线程是可以相互独立工作的。

下图描述的就是mysql复制的流程:
MySQL复制如何工作

主从复制配置实战

下面我以docker系统安装MySQL 5.7的主从同步来演示主从同步过程。

  1. 拉取mysql镜像
$ docker pull mysql:5.7
  1. 创建mysql在宿主机对应的目录映射
$ mkdir -p /usr/local/mysql57-master/{logs,data}
$ mkdir -p /usr/local/mysql57-slave/{logs,data}
  1. 启动mysql容器(这里分别用3306和3316作为主从端口)
$ docker run -d --name mysql57-master \
           -v ./usr/local/mysql57-master:/var/lib/mysql \
           -e MYSQL_ROOT_PASSWORD=root@123 \
           -p 3306:3306 \
           mysql:5.7
$ docker run -d --name mysql57-slave \
           -v ./usr/local/mysql57-slave:/var/lib/mysql \
           -e MYSQL_ROOT_PASSWORD=root@123 \
           -p 3316:3306 \
           mysql:5.7
  1. 配置master节点
# 进入容器
$ docker exec -it mysql57-master /bin/bash

# 修改my.cnf配置,开启日志功能、配置server-id
[mysqld] 
## 同一局域网内注意要唯一
server-id=100
## 开启二进制日志功能
log-bin=mysql-bin

# 重启数据库,使配置生效,并重新启动容器
$ service mysql restart
$ docker start mysql57-master

# 再次进入master节点容器:创建数据同步用户,并授予该用户 REPLICATION SLAVE权限和REPLICATION CLIENT权限,用于在主从间同步数据
> CREATE USER 'slave01'@'%' IDENTIFIED BY '1234567';
> GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave01'@'%';
  1. 配置slave节点
# 进入容器
$ docker exec -it mysql57-slave /bin/bash

# 修改my.cnf配置,开启日志功能、配置server-id
[mysqld]
## 设置server_id,注意要唯一
server-id=101 
## 开启二进制日志功能,以备Slave作为其它Slave的Master时使用
log-bin=mysql-slave-bin  
## relay_log配置中继日志
relay_log=edu-mysql-relay-bin
#复制的数据写入日志中
log_slave_updates=1

# 重启数据库,使配置生效,并重新启动容器
$ service mysql restart
$ docker start mysql57-slave
  1. 连接master和slave节点
    slave节点
> change master to master_host='172.17.0.2', master_user='slave01', master_password='1234567', master_port=3306, master_log_file='mysql-bin.000001', master_log_pos=0;

# 开始复制
> start slave

# 查看主从同步状态
show slave status \G;

在未同步情况下,SlaveIORunning 和 SlaveSQLRunning 都是No,因为我们还没有开启主从复制过程。
使用start slave开启主从复制过程,然后再次查询主从同步状态(show slave status),SlaveIORunning 和 SlaveSQLRunning 应该都是YES。

在这里插入图片描述

另外,通过 show processlist 可以查看到同步中所用到的三个线程:

# 主节点上由从库I/O线程发起的连接
mysql> show processlist \G
*************************** 1. row ***************************
     Id: 17
   User: slave01
   Host: 172.17.0.3:41806
     db: NULL
Command: Binlog Dump
   Time: 12573
  State: Master has sent all binlog to slave; waiting for more updates
   Info: NULL


# 从节点的两个线程
mysql> show processlist \G
*************************** 2. row ***************************
     Id: 30
   User: system user
   Host:
     db: NULL
Command: Connect
   Time: 12489
  State: Waiting for master to send event
   Info: NULL
*************************** 3. row ***************************
     Id: 31
   User: system user
   Host:
     db: NULL
Command: Connect
   Time: 12102
  State: Slave has read all relay log; waiting for the slave I/O thread to update it
   Info: NULL

下次我们会继续以mysql为例来详细讲解复制的几种实现方式:基于语句复制、基于行复制,并分析这两种复制方式的优缺点。

更多分布式、区块链技术分享,请关注公众号【伟达实验室】

伟达实验室

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值