如有笔误,欢迎留言指正或讨论!

一、概述

1.1、什么是主从复制?

主从复制就是将主数据库的 DDL 和 DML 通过二进制日志传到从服务器上,从数据库对这些日志进行重新执行,使得主从数据保持一致性。

二、 主从复制原理

2.1、主从复制结构图

mysql主从复制结构图

  • 主库 在事物提交时会把变更的数据作为 事件 记录到二进制日志Binlog中;
  • 从库 创建 I/O线程 用来连接主库请求更新的数据,主库收到请求后会通过 dump线程 读取binlog日志数据并发送给从库;
  • 从库 收到数据后会先写入到 relay-log日志 中,从库会有一个 sql线程 实时监控relay-log日志中更新的数据,然后执行的相关操作;

三、搭建主从复制实例

3.1、docker运行mysql(8.0.30)实例

  • 首先拉取mysql(8.0.30)镜像 (本机需要有docker环境)
    docker pull mysql:8.0.31

3.1.1、主库mysql实例

/var/lib/mysql/mysql_binLog

  • 启动主节点mysql实例
    docker run --name mysql_master -p 3307:3306 -v ~/mydata/mysql_master/data:/var/lib/mysql -v ~/mydata/mysql_master/conf:/etc/mysql/conf.d:rw -v ~/mydata/mysql_master/log:/var/log -e MYSQL_ROOT_PASSWORD=Master123@2022 -e TZ=Asia/Shanghai -d mysql:8.0.30 --default-authentication-plugin=mysql_native_password --character-set-server=utf8mb4 --collation-server=utf8mb4_bin
  • 创建主节点的 my.cnf 配置文件(~/mydata/mysql_master/conf/my.cnf)
    [mysqld]
    ## 设置server_id,同一局域网中需要唯一
    server_id=101
    ## 指定不需要同步的数据库名称
    binlog-ignore-db=mysql
    ## 开启二进制日志功能
    log-bin=mall-mysql-bin
    ## 设置二进制日志使用内存大小(事务)
    binlog_cache_size=1M
    ## 设置使用的二进制日志格式(mixed,statement,row)
    binlog_format=mixed
    ## 二进制日志过期清理时间。默认值为0,表示不自动清理。
    expire_logs_days=7
    ## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
    ## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
    slave_skip_errors=1062
  • 修改完配置后重启实例
    docker restart mysql_master
  • 为了安全起见在主节点创建一个 数据同步用户
    docker exec -it mysql_master bin/bash
    
    mysql -uroot -pMaster123@2022
    
    CREATE USER 'slave'@'%' IDENTIFIED BY 'Slave@123456';
    
    GRANT ALL PRIVILEGES ON *.* TO 'slave'@'%'WITH GRANT OPTION;
    
    flush privileges;
    

3.1.2、从库mysql实例

  • 启动从节点mysql实例
    docker run --name mysql_slave -p 3308:3306 -v ~/mydata/mysql_slave/data:/var/lib/mysql -v ~/mydata/mysql_slave/conf:/etc/mysql/conf.d:rw -v ~/mydata/mysql_slave/log:/var/log -e MYSQL_ROOT_PASSWORD=Slave123@2022 -e TZ=Asia/Shanghai -d mysql:8.0.30 --default-authentication-plugin=mysql_native_password --character-set-server=utf8mb4 --collation-server=utf8mb4_bin
  • 创建从节点的 my.cnf 配置文件(~/mydata/mysql_slave/conf/my.cnf)
    [mysqld]
    ## 设置server_id,同一局域网中需要唯一
    server_id=102
    ## 指定不需要同步的数据库名称
    binlog-ignore-db=mysql
    ## 开启二进制日志功能,以备Slave作为其它数据库实例的Master时使用
    log-bin=mall-mysql-slave1-bin
    ## 设置二进制日志使用内存大小(事务)
    binlog_cache_size=1M
    ## 设置使用的二进制日志格式(mixed,statement,row)
    binlog_format=mixed
    ## 二进制日志过期清理时间。默认值为0,表示不自动清理。
    expire_logs_days=7
    ## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
    ## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
    slave_skip_errors=1062
    ## relay_log配置中继日志
    relay_log=mall-mysql-relay-bin
    ## log_slave_updates表示slave将复制事件写进自己的二进制日志
    log_slave_updates=1
    ## slave设置为只读(具有super权限的用户除外)
    read_only=1
  • 修改完配置后重启实例
    docker restart mysql_slave

3.2、调试主从复制数据

  • 进入主节点数据库的mysql客户端,查看主节点数据库状态

    docker exec -it mysql_master bin/bash
    
    mysql -uroot -pMaster123@2022
    
    show master status;
    #mysql> show master status; 执行结果如下:
    #+---------------+----------+--------------+------------------+-------------------+
    #| File          | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
    #+---------------+----------+--------------+------------------+-------------------+
    #| binlog.000004 |      873 |              |                  |                   |
    #+---------------+----------+--------------+------------------+-------------------+
    #1 row in set (0.00 sec)
  • 进入从节点数据库的mysql客户端,配置主从复制信息

    docker exec -it mysql_slave /bin/bas
    
    mysql -uroot -pSlave123@2022
    
    change master to master_host='192.168.16.108', master_user='slave', master_password='Slave@123456', master_port=3307, master_log_file='binlog.000010', master_log_pos=844, master_connect_retry=30;
    
    show slave status \G;
    #mysql> show slave status \G; 查看主从同步状态, 执行结果如下:
    #主要看下:Slave_IO_Running: No 、 Slave_SQL_Running: No
    #*************************** 1. row ***************************
    #               Slave_IO_State:
    #                  Master_Host: 127.0.0.1
    #                  Master_User: slave
    #                  Master_Port: 3307
    #                Connect_Retry: 30
    #              Master_Log_File: mall-mysql-bin.000004
    #          Read_Master_Log_Pos: 157
    #               Relay_Log_File: 1d6b78b3c915-relay-bin.000001
    #                Relay_Log_Pos: 4
    #        Relay_Master_Log_File: mall-mysql-bin.000004
    #             Slave_IO_Running: No
    #            Slave_SQL_Running: No
    #              Replicate_Do_DB:
    #          Replicate_Ignore_DB:
    # ..........
  • 进入从节点实例,连接mysql终端后,开启主从同步

    start slave;
    
    show slave status \G;
    #mysql> show slave status \G; 查看主从同步状态, 执行结果如下:
    #主要看下:Slave_IO_Running: Yes 、 Slave_SQL_Running: Yes
    #*************************** 1. row ***************************
    #               Slave_IO_State: Connecting to source
    #                  Master_Host: 127.0.0.1
    #                  Master_User: slave
    #                  Master_Port: 3307
    #                Connect_Retry: 30
    #              Master_Log_File: mall-mysql-bin.000004
    #          Read_Master_Log_Pos: 157
    #               Relay_Log_File: 1d6b78b3c915-relay-bin.000001
    #                Relay_Log_Pos: 4
    #        Relay_Master_Log_File: mall-mysql-bin.000004
    #             Slave_IO_Running: Yes
    #            Slave_SQL_Running: Yes
    #              Replicate_Do_DB:
    #          Replicate_Ignore_DB:
    # ..........
  • 主从复制的测试方法有很多,可以在主实例中创建一个数据库,看看从实例中是否有该数据库,如果有,表示主从复制已经搭建成功。