• 使用docker-compose搭建mysql主从复制


    写在前面

    写此博客,主要是简化mysql主从搭建,同时给需要学习mysql主从的同学一个现成的环境。

    编写master.sh脚本

    此脚本主要是根据环境变量,创建出用于主从同步的用户。关于为什么要创建出master,slave脚本,是为了区分master和slave环境,因为只要把sql和sh文件放到master目录下面,master在第一次初始化的时候,会自动执行里面的文件内容

    mkdir -p init init/master init/slave
    cat > init/master/master.sh <<EOF
    #!/bin/bash
    #定义用于同步的用户名
    MASTER_SYNC_USER=\${MASTER_SYNC_USER:-sync_admin}
    #定义用于同步的用户密码
    MASTER_SYNC_PASSWORD=\${MASTER_SYNC_PASSWORD:-123456}
    #定义用于登录mysql的用户名
    ADMIN_USER=\${ADMIN_USER:-root}
    #定义用于登录mysql的用户密码
    ADMIN_PASSWORD=\${ADMIN_PASSWORD:-123456}
    #定义运行登录的host地址
    ALLOW_HOST=\${ALLOW_HOST:-%}
    #定义创建账号的sql语句
    CREATE_USER_SQL="CREATE USER '\$MASTER_SYNC_USER'@'\$ALLOW_HOST' IDENTIFIED BY '\$MASTER_SYNC_PASSWORD';"
    #定义赋予同步账号权限的sql,这里设置两个权限,REPLICATION SLAVE,属于从节点副本的权限,REPLICATION CLIENT是副本客户端的权限,可以执行show master status语句
    GRANT_PRIVILEGES_SQL="GRANT SELECT,REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO '\$MASTER_SYNC_USER'@'\$ALLOW_HOST';"
    #定义刷新权限的sql
    FLUSH_PRIVILEGES_SQL="FLUSH PRIVILEGES;"
    #执行sql
    mysql -u"\$ADMIN_USER" -p"\$ADMIN_PASSWORD" -e "\$CREATE_USER_SQL \$GRANT_PRIVILEGES_SQL \$FLUSH_PRIVILEGES_SQL"
    EOF
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    编写slave.sh脚本

    slave主要是去master查询最新的pos位置和binlog文件名称,然后创建同步需要的相关信息,然后执行start slave;

    cat >init/slave/slave.sh<<EOF
    #定义连接master进行同步的账号
    SLAVE_SYNC_USER="\${SLAVE_SYNC_USER:-sync_admin}"
    #定义连接master进行同步的账号密码
    SLAVE_SYNC_PASSWORD="\${SLAVE_SYNC_PASSWORD:-123456}"
    #定义slave数据库账号
    ADMIN_USER="\${ADMIN_USER:-root}"
    #定义slave数据库密码
    ADMIN_PASSWORD="\${ADMIN_PASSWORD:-123456}"
    #定义连接master数据库host地址
    MASTER_HOST="\${MASTER_HOST:-%}"
    #连接master数据库,查询二进制数据,并解析出logfile和pos,这里同步用户要开启 REPLICATION CLIENT权限,才能使用SHOW MASTER STATUS;
    RESULT=\`mysql -u"\$SLAVE_SYNC_USER" -h\$MASTER_HOST -p"\$SLAVE_SYNC_PASSWORD" -e "SHOW MASTER STATUS;" | grep -v grep |tail -n +2| awk '{print \$1,\$2}'\`
    #解析出logfile
    LOG_FILE_NAME=\`echo \$RESULT | grep -v grep | awk '{print \$1}'\`
    #解析出pos
    LOG_FILE_POS=\`echo \$RESULT | grep -v grep | awk '{print \$2}'\`
    #设置连接master的同步相关信息
    SYNC_SQL="change master to master_host='\$MASTER_HOST',master_user='\$SLAVE_SYNC_USER',master_password='\$SLAVE_SYNC_PASSWORD',master_log_file='\$LOG_FILE_NAME',master_log_pos=\$LOG_FILE_POS,get_master_public_key=1;"
    #开启同步
    START_SYNC_SQL="start slave;"
    #查看同步状态
    STATUS_SQL="show slave status\G;"
    mysql -u"\$ADMIN_USER" -p"\$ADMIN_PASSWORD" -e "\$SYNC_SQL \$START_SYNC_SQL \$STATUS_SQL"
    EOF
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    编写docker-compose.yml脚本

    version: '3'
    services:
      master:
        image: mysql:8.0.28
        container_name: mysql-master
        ports:
        - '3306:3306'
        restart: always
        hostname: mysql-master
        environment:
          MYSQL_ROOT_PASSWORD: "123456"
          MASTER_SYNC_USER: "sync"
          MASTER_SYNC_PASSWORD: "123456"
          ADMIN_USER: "root"
          ADMIN_PASSWORD: "123456"
          TZ: "Asia/Shanghai"
        deploy:
          resources:
            limits:
              memory: 512M
              cpus: 50m
        healthcheck:
          test: ["CMD","mysqladmin","-uroot","-p$${MYSQL_ROOT_PASSWORD}","ping","-h","localhost"]
          timeout: 2s
          interval: 10s
          retries: 5
          start_period: 5s
        logging:
          options:
            max-file: '1'
            max-size: '128k'
        command:
        -  "--server-id=1"
        -  "--character-set-server=utf8mb4"
        -  "--collation-server=utf8mb4_unicode_ci"
        -  "--log-bin=mysql-bin"
        -  "--sync_binlog=1"
        -  "--binlog-ignore-db=mysql"
        -  "--binlog-ignore-db=sys"
        -  "--binlog-ignore-db=performance_schema"
        -  "--binlog-ignore-db=information_schema"
        -  "--sql_mode=NO_AUTO_VALUE_ON_ZERO,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,PIPES_AS_CONCAT,ANSI_QUOTES"
        volumes:
        - ./init/master:/docker-entrypoint-initdb.d
        - ./data/master:/var/lib/mysql
      slave:
        image: mysql:8.0.28
        container_name: mysql-slave
        ports:
        - '3307:3306'
        restart: always
        hostname: mysql-slave
        environment:
          MYSQL_ROOT_PASSWORD: "123456"
          SLAVE_SYNC_USER: "sync"
          SLAVE_SYNC_PASSWORD: "123456"
          ADMIN_USER: "root"
          ADMIN_PASSWORD: "123456"
          MASTER_HOST: "mysql-master"
          TZ: "Asia/Shanghai"
        healthcheck: 
          test: ["CMD","mysqladmin","-uroot","-p$${MYSQL_ROOT_PASSWORD}","ping","-h","localhost"]
          timeout: 2s
          interval: 10s
          retries: 5
          start_period: 5s
        deploy:
          resources:
            limits:
              memory: 512M
              cpus: 50m
        logging:
          options:
            max-file: '1'
            max-size: '128k'
        depends_on:
          master:
            condition: service_healthy
        command:
        -  "--server-id=2"
        -  "--character-set-server=utf8mb4"
        -  "--collation-server=utf8mb4_unicode_ci"
        -  "--sql_mode=NO_AUTO_VALUE_ON_ZERO,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,PIPES_AS_CONCAT,ANSI_QUOTES"
        volumes:
        - ./init/slave:/docker-entrypoint-initdb.d
        - ./data/slave:/var/lib/mysql
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86

    启动准备

    最终结构

    根据上面的脚本,执行之后,应该会是如下结构
    在这里插入图片描述

    执行脚本

    docker-compose up -d
    
    • 1

    执行之后的效果
    在这里插入图片描述

    docker logs -f mysql-slave
    
    • 1

    查看mysql-slave日志,看到以下两个yes,就代表成功了
    在这里插入图片描述

    测试阶段

    连接信息
    在这里插入图片描述
    在这里插入图片描述

    主从同步效果

    3307是从节点
    在这里插入图片描述

    创建数据库,可以看到,在主节点创建数据库之后,从节点刷新就能看到
    在这里插入图片描述

    创建表及添加数据测试
    在这里插入图片描述
    在这里插入图片描述

    主从环境重启

    docker-compose restart
    
    • 1

    在这里插入图片描述
    重新连接数据库,查看从节点同步状态

    SHOW SLAVE STATUS;
    
    • 1

    可以看到,重启之后,同步也是正常的
    在这里插入图片描述

    当修改数据和新增数据,也是可以正常同步
    在这里插入图片描述
    在这里插入图片描述

    容器被删除,重新启动

    可以看到,容器已经被删除了,数据库也无法正常连接
    在这里插入图片描述
    在这里插入图片描述
    重启容器,查看同步状态,

    docker-compose up -d
    
    • 1

    在这里插入图片描述
    在从节点执行。可以看到,同步也是正常的

    SHOW SLAVE STATUS;
    
    • 1

    在这里插入图片描述

    验证同步效果.这里删除id=5的数据,新增id=7,9的数据
    可以看到,也是正常同步的
    在这里插入图片描述
    在这里插入图片描述

    从节点关闭,主节点继续写入数据

    这里测试,当从节点被关闭,然后主节点继续写入数据,然后从节点启动

    docker stop mysql-slave
    
    • 1

    在这里插入图片描述
    主节点写入数据
    这里将原本id=3的数据删除,修改id=7,9变为8,10,新增id=11的记录
    在这里插入图片描述
    启动从节点,并查看同步状态

    docker start mysql-slave
    
    • 1

    在这里插入图片描述
    可以看到,同步也是正常开启的
    在这里插入图片描述
    数据也是正常同步
    在这里插入图片描述

    从节点删除,主节点继续写入数据,从节点重新创建

    docker rm -f mysql-slave
    
    • 1

    可以看到,从节点容器已经被删除,也无法正常连接
    在这里插入图片描述
    在这里插入图片描述

    主节点操作数据
    这里创建testa表,新增一些数据,test表删除id=10的数据,修改id=11的数据改为id=15
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    创建从节点
    在这里插入图片描述
    查看日志,可以看到,这里test.test这个表,id=11的数据重复了,这里我们登录从节点,将id=11的这条数据删除,然后重新开启同步
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    重新开启同步

    STOP SLAVE;
    START SLAVE;
    SHOW SLAVE STATUS;
    
    • 1
    • 2
    • 3

    可以看到,这里是yes,这个时候我们再去看日志
    在这里插入图片描述

    可以看到,这里同步失败了,同时并没有提示我们是那条数据,所以我们不能通过删除或者修改数据来修复问题,因此我们需要将数据库删除,然后重新修改同步的pos位置信息,重新启动同步在这里插入图片描述

    删除test数据库
    在这里插入图片描述
    修改pos信息,重新启动同步

    STOP SLAVE;
    RESET SLAVE;
    CHANGE MASTER TO master_log_pos=0;
    START SLAVE;
    SHOW SLAVE STATUS;
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述
    可以看到,数据已经同步过来了
    在这里插入图片描述
    测试同步
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    写在后面

    基于docker-compose搭建mysql主从已经结束,这里主要演示了如何一键搭建mysql主从,同时测试在各种环境下,还能保证主从同步。但是单主从同步肯定也无法满足企业的需求,有兴趣的同学可以研究一些主主双写同步,然后通过nginx搭建主备模式,达到高可用。当然,根据我的猜想,是可以实现的
    文中一键搭建环境mysql主从复制脚本

  • 相关阅读:
    使用 requestAnimationFrame 提升 web 性能
    WordPress 提示“此站点遇到了致命错误”的解决方法
    微前端(乾坤)使用记录
    WorkPlus定制化的局域网会议软件,提供安全稳定的会议体验
    1.12反向传播误差到更多层
    BUSMASTER使用记录(一):基本收发、报文过滤、报文录制和数据回放
    C++ 01
    OFDM 十六讲 3- OFDM Waveforms
    基于C语言的排序算法汇编
    JavaScript 33. Promise
  • 原文地址:https://blog.csdn.net/qq_42413011/article/details/126914080