mysql 主从架构详解

主从复制简介

MySQL主从复制(Replication)指的是两台或以上数据库实例服务器,通过二进制日志实现数据的"同步"关系。

需要注意的是,MySQL主从复制并不是说其工作模式是同步的,实际上,MySQL主从复制(Replication)是一个异步工作模式。

主从复制的前提

  1. 需要2台以上数据库实例,时间同步,网络通畅,server_id不同,区分不同角色(即主库和从库);
  2. 主库开启binlog,建立专用复制用户;
  3. 从库需要提前"补课"(将之前"落下"的数据补全),如果主库也是没数据的,这一步可以省略;
  4. 从库需要确认主库的连接信息,复制起点等;
  5. 从库需要开启专用的复制线程;

主从复制架构原理

  1. 从库执行"CHANGE MASTER TO ..."命令,执行命令成功后会将这些主库的链接信息记录在"master.info"文件中;
  2. 执行"START SLAVE"命令后,从库会开启IO线程和SQL线程这两个线程,其中IO线程负责发送请求到主库,有关主库的链接信息在"master.info"文件中都有记录;
  3. 主库分配了一个binlog_dump线程来响应从库的IO线程,我们可以通过"SHOW PROCESSLIST"命令来查看响应的binlog_dump线程;
  4. 从库的IO线程会请求新日志,有关向主库请求的日志位置点信息在"master.info"文件中都有记录;
  5. 主库的binlog_dump线程接收从库的IO线程请求后,会截取主库的二进制日志文件,并将结果返回给从库的IO线程;
  6. 从库的IO线程接收到主库的binlog后,日志先发送到网卡的缓存区域中,此时由网络层返回ACK给主库,主库工作完成;
  7. 从库的IO线程最终会将数据从网卡的缓冲区拉取并写入中继日志文件中以落地到本地磁盘,于此同时会更新"master.info"文件中记录的位置点信息,以便于下一次从库IO线程知道从哪个位置点请求"新日志",I/O线程工作完成。
  8. 从库的SQL线程读取"relay-log.info"文件,获取上一次中继日志文件执行到的位置点;
  9. 从库的SQL线程根据上一步获得中继日志文件的位置点后,在该位置点继续向后执行新的"relay-log"日志,而后会更新"relay-log.info"文件,,以便于下一次从库SQL线程知道从哪个位置点读取"新日志",主从复制流程基本结束。

主从涉及到的文件介绍

主库:

  • binlog文件:默认存储在数据目录下,用于存储用户的操作记录,我们可以基于"log_bin_basename"来制定存储的路径及文件名前缀。

    SELECT @@log_bin_basename;

从库:

  • relay-log文件: 默认存储在数据目录下,用于接收存储binlog,也称为"中继日志"。我们可以基于"relay_log_basename"来手动指定存储路径。

    SELECT @@relay_log_basename;

  • master.info文件: 默认存储在数据目录下,用于存储主库的链接信息,已经接受的binlog位置点信息等数据。我们可以基于"master_info_repository"来手动指定该文件存储位置。

    SELECT @@master_info_repository;

  • relay-log.info文件: 默认存储在数据目录下,从库会单独开启一个I/O线程从主库拉取二进制日志并存储中继日志(上面提到的"relay-log"文件)中,而后从库开启一个SQL线程基于中继日志进行回放,以达到和主库同样的数据。而relay-log.info文件就是用于记录从库回放到relay-log的位置点,这是为了防止从库突然宕机后,重启服务器后知道上一次回放的位置点,而后基于该记录的位置点继续往下执行SQL。我们可以基于"relay_log_info_repository"来手动指定该文件存储位置。

    SELECT @@relay_log_info_repository ;

主从涉及到的线程介绍

主库:

  • binlog_dump线程: 用来接收从库请求,并且投递binlog给从库。查看方式:

    SHOW PROCESSLIST;

从库:

  • IO线程:用于向主库请求,接收和存储binlog日志。

  • SQL线程:用于回放中继日志(上面提到的"relay-log"文件),执行"relay-log"文件的SQL语句并将执行的位置点记录在"relay-log.info"文件中。查看方式:

    SHOW SLAVE STATUS\G;

主从复制部署

架构

主机 角色
192.168.153.12 master
192.168.153.13 slave

两台机器安装mysql

可查看《mysql5.7版本部署》章节

时间配置

复制代码
timedatectl set-timezone Asia/Shanghai
ntpdate ntp1.aliyun.com

配置主从

  1. 主配置文件:

    cat /etc/my.cnf
    [mysqld]
    bind-address = 0.0.0.0
    server-id=1
    log-bin=/data/mysql/logs/mysql-bin.log
    log_error = /data/mysql/logs/mysql-error.log
    default-time-zone='+8:00'
    log_timestamps=SYSTEM
    binlog_format=ROW
    binlog_row_image=FULL
    expire_logs_days=14
    max_binlog_size=1G
    sync_binlog=1
    innodb_flush_log_at_trx_commit=1
    innodb_buffer_pool_size=600M
    innodb_log_file_size=2G

    mkdir /data/mysql/logs
    touch /data/mysql/logs/mysql-error.log
    chown -R mysql:mysql /data/mysql/logs
    systemctl restart mysqld
    systemctl status mysqld

  2. 从配置文件:

    cat /etc/my.cnf
    [mysqld]
    bind-address = 0.0.0.0
    server-id=2
    log-bin=/data/mysql/logs/mysql-bin.log
    log_error = /data/mysql/logs/mysql-error.log
    default-time-zone='+8:00'
    log_timestamps=SYSTEM
    relay_log=/data/mysql/logs/mysql-relay-bin
    relay_log_index=/data/mysql/logs/mysql-relay-bin.index
    read_only=1
    super_read_only=1
    slave_net_timeout = 60
    relay_log_recovery = ON
    sync_binlog = 1
    innodb_flush_log_at_trx_commit = 1
    innodb_buffer_pool_size = 600M
    innodb_log_file_size=2G

    mkdir /data/mysql/logs
    touch /data/mysql/logs/mysql-error.log
    chown -R mysql:mysql /data/mysql/logs
    systemctl restart mysqld
    systemctl status mysqld

  3. 主库建立复制用户

    MySQL 8.0之前版本创建复制用户

    GRANT REPLICATION SLAVE ON . TO repl@'192.168.153.%' IDENTIFIED BY '1qaz@WSX';

    MySQL 8.0之后版本创建复制用户

    CREATE USER repl@'192.168.153.%' IDENTIFIED BY '1qaz@WSX';

  4. 主库备份恢复到从库,如果建立主从之前主库里面有数据,需要做此操作。

    mysqldump -uroot -p'1qaz@WSX' -A --master-data=2 --single-transaction > /tmp/all_db.sql
    mysql -uroot -p'1qaz@WSX' < /tmp/all_db.sql

  5. 主库查看二进制日志坐标,从库建立连接

    mysql> show master status ;
    +------------------+----------+--------------+------------------+-------------------+
    | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
    +------------------+----------+--------------+------------------+-------------------+
    | mysql-bin.000002 | 154 | | | |
    +------------------+----------+--------------+------------------+-------------------+
    1 row in set (0.00 sec)

    file : 从哪个日志文件开始推送日志文件

    position : 从哪个位置开始推送日志

    binlog_ignore_db : 指定不需要同步的数据库

    此方法在如果主库里面有数据,业务停用的时候可以,没有新的数据增加,但当业务还在使用,有新的数据增加的时候需要查看从库备份过来的数据的最后一个Position为起点。

  6. 从库建立主库的连接信息,并确定复制的起点

    CHANGE MASTER TO MASTER_HOST='192.168.153.12', MASTER_USER='repl', MASTER_PASSWORD='1qaz@WSX' , MASTER_PORT=3306, MASTER_LOG_FILE='mysql-bin.000002' ,MASTER_LOG_POS=154, MASTER_CONNECT_RETRY=10;

  7. 从库开启专用的复制线程

    START SLAVE;

  8. 验证主从复制状态

plain 复制代码
SHOW SLAVE STATUS\G

部署成功

  1. 如果主从复制搭建不成功,可以重置主从配置信息,而后重做上述操作。

    STOP SLAVE;
    RESET SLAVE ALL;

主从复制中从库的线程管理

复制代码
# 启动从库IO线程和SQL线程
START SLAVE;

# 停止从库IO线程和SQL线程
STOP SLAVE;

# 只启动从库的SQL线程
START SLAVE SQL_THREAD;

# 只启动从库的IO线程
START SLAVE IO_THREAD;

# 只停止从库的SQL线程
STOP SLAVE SQL_THREAD;

# 只停止从库的IO线程
STOP SLAVE IO_THREAD;

解除从库身份

复制代码
# 在解除从库之前,需要先停止所有的线程,即IO线程和SQL线程
STOP SLAVE;  

# 解除从库的所有配置
RESET SLAVE ALL;  

#  解除后再次查看从库的状态
SHOW SLAVE STATUS\G