美文网首页
DBA(MySQL)学习-主从复制基础

DBA(MySQL)学习-主从复制基础

作者: 慕男 | 来源:发表于2019-06-27 18:55 被阅读0次

    1. 主从复制

    1.1 介绍

    依赖于二进制日志的,“实时”备份的多节点架构
    

    1.2 主从复制的前提(如何搭建主从复制)

    (1)至少2个实例
    (2)不同的server_id
    (3)主库要开启二进制日志
    (4)主库需要授权一个副库专用的复制用户
    (5)主库数据备份
    (6)开启专用复制线程
    

    2. 搭建主从复制

    2.1 搭建多实例

    (1) 准备多个目录
    mkdir -p /data/330{7,8,9}/data
    
    (2)准备配置文件
    cat > /data/3307/my.cnf <<EOF
    [mysqld]
    basedir=/app/mysql
    datadir=/data/3307/data
    socket=/data/3307/mysql.sock
    log_error=/data/3307/mysql.log
    port=3307
    server_id=7
    log_bin=/data/3307/mysql-bin
    EOF
    
    cat > /data/3308/my.cnf <<EOF
    [mysqld]
    basedir=/app/mysql
    datadir=/data/3308/data
    socket=/data/3308/mysql.sock
    log_error=/data/3308/mysql.log
    port=3308
    server_id=8
    log_bin=/data/3308/mysql-bin
    EOF
    
    cat > /data/3309/my.cnf <<EOF
    [mysqld]
    basedir=/app/mysql
    datadir=/data/3309/data
    socket=/data/3309/mysql.sock
    log_error=/data/3309/mysql.log
    port=3309
    server_id=9
    log_bin=/data/3309/mysql-bin
    EOF
    
    (3)初始化三套数据
    mv /etc/my.cnf /etc/my.cnf.bak
    mysqld --initialize-insecure  --user=mysql --datadir=/data/3307/data --basedir=/app/mysql
    mysqld --initialize-insecure  --user=mysql --datadir=/data/3308/data --basedir=/app/mysql
    mysqld --initialize-insecure  --user=mysql --datadir=/data/3309/data --basedir=/app/mysql
    
    (4) systemd管理多实例
    cd /etc/systemd/system
    cp mysqld.service mysqld3307.service
    cp mysqld.service mysqld3308.service
    cp mysqld.service mysqld3309.service
    
    vim mysqld3307.service
    ExecStart=/app/mysql/bin/mysqld  --defaults-file=/data/3307/my.cnf
    vim mysqld3308.service
    ExecStart=/app/mysql/bin/mysqld  --defaults-file=/data/3308/my.cnf
    vim mysqld3309.service
    ExecStart=/app/mysql/bin/mysqld  --defaults-file=/data/3309/my.cnf
    
    (5)授权
    chown -R mysql.mysql /data/*
    
    (6)启动
    systemctl start mysqld3307.service
    systemctl start mysqld3308.service
    systemctl start mysqld3309.service
    
    (7)验证多实例
    netstat -lnp|grep 330
    mysql -S /data/3307/mysql.sock -e "select @@server_id"
    mysql -S /data/3308/mysql.sock -e "select @@server_id"
    mysql -S /data/3309/mysql.sock -e "select @@server_id"
    

    2.2 检测server_id

    mysql -S /data/3307/mysql.sock -e "select @@server_id"
    mysql -S /data/3308/mysql.sock -e "select @@server_id"
    mysql -S /data/3309/mysql.sock -e "select @@server_id"
    

    2.3 检查3307(主库)的二进制日志情况

    mysql -S /data/3307/mysql.sock -e "show variables like '%log_bin%'"
    

    2.4 主库创建复制用户(3307)(用户=repl)

    mysql [(none)]>grant replication slave on *.* to repl@'10.0.0.%' identified by '123';
    

    2.5 进行主库数据备份

    mysqldump -S /data/3307/mysql.sock -A --master-data=2 -R -E --triggers --single-transaction >/tmp/3307full.sql
    

    2.6 恢复数据到从库(3308)

    [root@db01 /data]# mysql -S /data/3308/mysql.sock
    mysql [none]>set sql_log_bin=0;
    mysql [none]>source /tmp/3307full.sql;
    

    2.7 通知从库一些复制的信息

    CHANGE MASTER TO
    MASTER_HOST='10.0.0.51',
    MASTER_USER='repl',
    MASTER_PASSWORD='123',
    MASTER_PORT=3307,
    MASTER_LOG_FILE='master2-bin.002',
    MASTER_LOG_POS=444,
    MASTER_CONNECT_RETRY=10;
    
    mysql [(none)]>start slave;
    

    3. 主从复制工作过程

    3.1 名词认识

    文件:
       主库:binlog
       从库:relay-log(中继日志)、master.info(主库信息文件)、relay-log.info(中继日志应用信息)
    线程:
        主库:binlog_dump_thread (二进制投递线程)查看方法:mysql [(none)]>show processlist;
        从库:IO_Thread:从库的I/O线程:请求和接受binlog
              SQL_Thread:从库的SQL线程:回放日志
    

    3.2 工作原理

    image.png
    (1)从库执行change master to 语句,会立即将主库信息记录到从库的master.info中
    (2)从不高库执行 stat slave ,会立即生成TO_T和SQL_T
    (3)IO_T读取master.info文件,获取到主库信息
    (4) 主库会生成一个准备binlog DUMP线程,来响应从库
    (5)IO_T根据master.info记录的binlog文件名和position号,请求主库DUMP最新日志
    (6)主库 DUMP线程检查主库的binlog日志,如果有新的,TP(传送)给从从库的IO_T
    (7)IO_T将收到的日志存储到了TCP/IP 缓存,立即返回ACK给主库 ,主库工作完成
    (8)IO_T会更新master.info文件重置binlog位置点信息
    (9)从库IO_T会将binl,写入到relay-log中
    (10)SQL_T读取relay-log.info文件,获取到上次执行到的relay-log的位置,作为起点,回放relay-log
    (11)SQL_T按照位置点往下执行relaylog日志。
    (12)SQL_T执行完成后重新更新relay-log.info
    (13)relay-log会有自动清理的功能。
    

    细节:
    主库发生了信息的修改,更新二进制日志完成后,会发送一个“信号”给Dump_T,Dump_T通知给IO_T线程

    4. 主从复制监控及故障处理分析

    4.1 主从监控

    主库:show processlist;
          正常状态:
     mysql [(none)]>show processlist;
    +----+------+-----------------+------+-------------+------+---------------------------------------------------------------+------------------+
    | Id | User | Host            | db   | Command     | Time | State                                                         | Info             |
    +----+------+-----------------+------+-------------+------+---------------------------------------------------------------+------------------+
    | 19 | repl | 10.0.0.51:28599 | NULL | Binlog Dump | 1920 | Master has sent all binlog to slave; waiting for more updates | NULL             |
    | 20 | root | localhost       | NULL | Query       |    0 | starting                                                      | show processlist |
    +----+------+-----------------+------+-------------+------+---------------------------------------------------------------+------------------+
    2 rows in set (0.00 sec)
    
    从库:show slave status\G
    
    *************************** 1. row ***************************
    主库的信息:
            Slave_IO_State: Waiting for master to send event
                      Master_Host: 10.0.0.51                 --->主库的IP
                      Master_User: repl                      --->复制用户名
                      Master_Port: 3307                      --->主库的端口
                      Connect_Retry: 10                      ---> 断练之后重试次数
                      Master_Log_File: mysql-bin.000002      --->主库获取到的binlog文件名
                      Read_Master_Log_Pos: 444               --->已经获取到的binlog的位置号
    
    从库的relaylog的信息:(relay-log.info)
                      Relay_Log_File: db01-relay-bin.000002  --->从库已经运行过的relaylog的文件名
                      Relay_Log_Pos: 320                     --->从库已经运行过的relaylog的位置点
    从库复制线程工作状态:
                      Slave_IO_Running: Yes
                      Slave_SQL_Running: Yes
    过滤复制相关的状态:
                      Replicate_Do_DB: 
                      Replicate_Ignore_DB: 
                      Replicate_Do_Table: 
                      Replicate_Ignore_Table: 
                      Replicate_Wild_Do_Table: 
                      Replicate_Wild_Ignore_Table:
    从库延时主库的时间:
                      Seconds_Behind_Master: 0
    从库线程报错详细信息:
                      Last_IO_Errno: 0                        --->IO报错的号码
                      Last_IO_Error:                          --->IO报错的具体信息
                      Last_SQL_Errno: 0                       --->SQL报错的号码
                      Last_SQL_Error:                         --->SQL线程报错的具体原因
    延时从库:
                      SQL_Delay:  0                           --->延时从库设定的时间
                      SQL_Remaining_Delay: NULL               --->延时操作的剩余时间
    GTID复制信息:
                      Retrieved_Gtid_Set:                     --->接收到的GTID的格式  
                      Executed_Gtid_Set:                      --->执行的GTID的个数
    

    4.2 主从故障的分析及处理

    从库复制线程的状态
                      Slave_IO_Running: Yes
                      Slave_SQL_Running: Yes
    从库线程报错详细信息:
                      Last_IO_Errno: 0
                      Last_IO_Error: 
                      Last_SQL_Errno: 0
                      Last_SQL_Error: 
    

    4.2.1 IO线程故障

    (1)连接主库连接不上
    出现
                      Slave_IO_Running: Connecting
    原因:
           网络不通、防火墙、
           IP不对、port不对、用户名,密码不对、skip_name_reslove、连接数上限
    判断于以下错误对比:
    [root@db01 ~]# mysql -urepl -p123 -h 10.0.0.51 -P3308
    mysql: [Warning] Using a password on the command line interface can be insecure.
    ERROR 1130 (HY000): Host '10.0.0.51' is not allowed to connect to this MySQL server
    
    [root@db01 ~]# mysql -urepl -p123 -h 10.0.0.52 -P3307
    mysql: [Warning] Using a password on the command line interface can be insecure.
    ERROR 2003 (HY000): Can't connect to MySQL server on '10.0.0.52' (110)'
    
    [root@db01 ~]# mysql -urepl -p111 -h 10.0.0.51 -P3307
    mysql: [Warning] Using a password on the command line interface can be insecure.
    ERROR 1045 (28000): Access denied for user 'repl'@'10.0.0.51' (using password: YES)
    
    [root@db01 ~]# mysql -urepll -p123 -h 10.0.0.51 -P3307
    mysql: [Warning] Using a password on the command line interface can be insecure.
    ERROR 1045 (28000): Access denied for user 'repll'@'10.0.0.51' (using password: YES)
    
    找到原因后,如何处理?
    stop slave;
    reset slave all ;
    CHANGE MASTER TO
      MASTER_HOST='10.0.0.51',
      MASTER_USER='repl',
      MASTER_PASSWORD='123',
      MASTER_PORT=3307,
      MASTER_LOG_FILE='mysql-bin.000001',
      MASTER_LOG_POS=154,
      MASTER_CONNECT_RETRY=10;
    start slave;
    (2)请求新的binlog
    出现
                      Slave_IO_Running: No
    分析:
    错误1:
    日志名不对
            从库信息:
                      Master_Log_File: mysql-bin.000002
                      Read_Master_Log_Pos: 444
    于全库备份文件对比
     20 --
     21 
     22 -- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000002', MASTER_LOG_POS=444;
     23                                                                                                                           
     24 --
    错误2:主库使用了reset master;语句
    主库出现mysql [(none)]>show master status;
    +------------------+----------+--------------+------------------+-------------------+
    | File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
    +------------------+----------+--------------+------------------+-------------------+
    | mysql-bin.000001 |      154 |              |                  |                   |
    +------------------+----------+--------------+------------------+-------------------+
    要想把最近的数据也能传到从库上就要从154开头的时候开始
    处理方法:
    
    处理:
    mysql -S /data/3308/mysql.sock 
    stop slave;
    reset slave all ;
    CHANGE MASTER TO
      MASTER_HOST='10.0.0.51',
      MASTER_USER='repl',
      MASTER_PASSWORD='123',
      MASTER_PORT=3307,
      MASTER_LOG_FILE='mysql-bin.000001',
      MASTER_LOG_POS=154,
      MASTER_CONNECT_RETRY=10;
    start slave;
    (3)写relaylog
    (4)更新master.info
    

    4.2.2 SQL线程故障

    (1)读relay-log.info
         读relay-log.,并执行日志
         更新relay-log.info
    以上文件损坏,最好是重新构建主从
    (2)为什么一条SQL语句执行不成功
         1.主从数据库版本差异较大
         2.主从数据库配置参数不一致(例如:sql_mode等)
         3.想要创建的对象已经存在
         4.想要删除或修改的对象不存在
         5.主键冲突  
         6.DML语句不符合表定义及约束时
    归根揭底的原因都是由于从库发生了写入操作.
    
    方法一:
    stop slave; 
    set global sql_slave_skip_counter = 1;
    #将同步指针向下移动一个,如果多次不同步,可以重复操作。
    start slave;
    方法二:
    /etc/my.cnf
    slave-skip-errors = 1032,1062,1007
    常见错误代码:
    1007:对象已存在
    1032:无法执行DML
    1062:主键冲突,或约束冲突
    
    但是,以上操作有时是有风险的,最安全的做法就是重新构建主从。把握一个原则,一切以主库为主.
    

    5. 主从延时原因分析

    从库延时主库的时间
    Seconds_Bxehind_Master:0 从库延时主库的时间(秒为单位)
    

    5.1 主库方面

    (1)日志写入不及时
        sync_binlog=1
    (2)主库并发业务较高
        “分布式”架构
    (3)从库太多
         级联主从
    对于Classic Replication:
    主库是有能力并发运行事务的,但是在Dumo_T在传输日志的时候,是以事件为单元传输日志的,所以导致事务的传输工作是串行方式的,这时在主库TPS很高时,会产生比较大的主从延时。
    

    怎么处理:从5.6开始加入GTID,在复制时,可以将串行的传输模式变成并行的
    除了GTID支持,还需要双一保证。

    5.2 从库方面

    Classic Replication:
    
    SQL线程只有一个,所以说只能串行执行relay的事务。
    怎么解决?
    多加几个SQL线程>>>在5.6中出现了多线程SQL
    只能针对不同库下的事务,才能并发
    到5.7版本加入了MTS,真正实现了事务级别的并发SQL
    

    6. 延时从库

    6.1 数据损坏

    物理损坏
    逻辑损坏
    对于传统的主从复制,比较擅长处理物理损坏。
    

    6.2 设置理念

    对SQL线程进行延时设置
    

    6.3 延时多久合适?

    一般企业,3-6小时
    

    6.4 如何设置?

    mysql>stop slave;
    mysql>CHANGE MASTER TO MASTER_DELAY = 300;
    mysql>start slave;
    mysql> show slave status \G
    SQL_Delay: 300
    SQL_Remaining_Delay: NULL
    

    6.5 如何使用延时从库

    6.5.1 思路

    mysql [(none)]>
    mysql [(none)]>create database delay charset utf8mb4;
    mysql [(none)]>use delay;
    mysql [delay]>create table t1(id int);
    mysql [delay]>insert into t1 values(1),(2),(3);
    mysql [delay]>commit;
    
    drop database delay;
    发现问题啦:
    (1)停止SQL线程,停止主库业务
    (2)模拟SQL手工恢复relaylog到drop之前的位置点
    (3)截取relaylog日志,找到起点(relay-log.info)和终点(drop操作)
    (4)恢复截取的日志,验证
    
    开始处理:
    1. 停从库的SQL线程 
    mysql -S /data/3308/mysql.sock 
    mysql> stop slave sql_thread;
    2. 找relaylog的起点和终点
    起点:
    Relay_Log_File: db01-relay-bin.000002
    Relay_Log_Pos: 476
    
    终点: 
    mysql> show relaylog events in 'db01-relay-bin.000002'
    | db01-relay-bin.000002 | 1149 | Query          |         7 |        2036 | drop database delay  
    
    3. 截取日志 
    [root@db01 ~]# mysqlbinlog --start-position=476 --stop-position=1149 /data/3308/data/db01-relay-bin.000002 >/tmp/relay.sql
    
    4. 恢复 
    mysql -S /data/3308/mysql.sock 
    set sql_log_bin=0;
    source /tmp/relay.sql
    

    7. 过滤复制

    主库:(了解)
    binlog_do_db
    binlog_ignore_db
    从库:在SQL线程回放日志时,进行控制过滤
                  Replicate_Do_DB: 
                  Replicate_Ignore_DB: 
                  Replicate_Do_Table: 
                  Replicate_Ignore_Table: 
                  Replicate_Wild_Do_Table: 
                  Replicate_Wild_Ignore_Table: 
    
    例子: 
    只需要复制xyz库的数据到从库
    [root@db01 ~]# vim  /data/3308/my.cnf
    replicate_do_db=xyz
    
    systemctl restart mysqld3308
    注意:如果有多个库的话,写多行即可。
    

    8. 半同步复制

    加载插件
    主:
    INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
    从:
    INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
    查看是否加载成功:
    show plugins;
    启动:
    主:
    SET GLOBAL rpl_semi_sync_master_enabled = 1;
    从:
    SET GLOBAL rpl_semi_sync_slave_enabled = 1;
    重启从库上的IO线程
    STOP SLAVE IO_THREAD;
    START SLAVE IO_THREAD;
    查看是否在运行
    主:
    show status like 'Rpl_semi_sync_master_status';
    从:
    show status like 'Rpl_semi_sync_slave_status';
    
    和传统复制区别:
    是一个插件形式提供的功能
    主库: ack_receiver
    从库:  ACK_send
    主库的 ack_re 线程 只有接收到 从库发来的ACK确认,主库事务才能commit成功
    从库的 Acksend只有等relaylog落地才能发送ACK 
    主库只会等10s  如果ACK还没收到的,会自动替换为异步复制。
    

    9.GTID复制(高可用环境)---为下节做准备

    9.1 重点

    gtid-mode=on
    enforce-gtid-consistency=true
    log-slave-updates=1               --->强制刷新从库二进制日志:1. 高可用(MHA)2. 级联复制的中间库
    

    9.2 清理环境

    pkill mysqld
    \rm -rf /data/*
    \rm -rf /data/*
    mkdir -p /data/mysql/data 
    mkdir -p /data/binlog/
    chown -R mysql.mysql /data
    

    9.3 准备配置文件

    主库db01:
    cat > /etc/my.cnf <<EOF
    [mysqld]
    basedir=/application/mysql/
    datadir=/data/mysql/data
    socket=/tmp/mysql.sock
    server_id=51
    port=3306
    secure-file-priv=/tmp
    autocommit=0
    log_bin=/data/binlog/mysql-bin
    binlog_format=row
    gtid-mode=on
    enforce-gtid-consistency=true
    log-slave-updates=1
    [mysql]
    prompt=db01 [\\d]>
    EOF
    
    slave1(db02):
    cat > /etc/my.cnf <<EOF
    [mysqld]
    basedir=/application/mysql
    datadir=/data/mysql/data
    socket=/tmp/mysql.sock
    server_id=52
    port=3306
    secure-file-priv=/tmp
    autocommit=0
    log_bin=/data/binlog/mysql-bin
    binlog_format=row
    gtid-mode=on
    enforce-gtid-consistency=true
    log-slave-updates=1
    [mysql]
    prompt=db02 [\\d]>
    EOF
    
    slave2(db03):
    cat > /etc/my.cnf <<EOF
    [mysqld]
    basedir=/application/mysql
    datadir=/data/mysql/data
    socket=/tmp/mysql.sock
    server_id=53
    port=3306
    secure-file-priv=/tmp
    autocommit=0
    log_bin=/data/binlog/mysql-bin
    binlog_format=row
    gtid-mode=on
    enforce-gtid-consistency=true
    log-slave-updates=1
    [mysql]
    prompt=db03 [\\d]>
    EOF
    

    9.4 初始化数据(所有节点)

    mysqld --initialize-insecure --user=mysql --basedir=/application/mysql  --datadir=/data/mysql/data
    

    9.5 启动数据库并创建复制用户

    /etc/init.d/mysqld.server start
    db01 [(none)]>grant replication slave on *.* to repl@'10.0.0.%' identified by '123';
    

    9.6 两个从库开启主从

    mysql -e "change master to master_host='10.0.0.51',master_user='repl',master_password='123' ,MASTER_AUTO_POSITION=1;start slave; "
    
     mysql -e "show slave status \G"|grep Yes
    

    配置完成

    相关文章

      网友评论

          本文标题:DBA(MySQL)学习-主从复制基础

          本文链接:https://www.haomeiwen.com/subject/fezkcctx.html