zoukankan      html  css  js  c++  java
  • MySQL主从复制

    第1章 企业高可用标准

    1.1 全年无故障率(非计划内故障停机)

    99.9%                 ----> 0.001*365*24*60=525.6  min   一般互联网公司级别
    99.99%                ----> 0.0001*365*24*60=52.56 min
    99.999%               ----> 0.0001*365*24*60=5.256 min    金融级别
    

    第2章 主从复制(MySQL Replication)

    1.1 简介

    1.1. 基于二进制日志复制的
    1.2. 主库的修改操作会记录二进制日志
    1.3. 从库会请求新的二进制日志并回放,最终达到主从数据同步
    1.4. 主从复制核心功能:
    辅助备份,处理物理损坏                   
    扩展新型的架构:高可用,高性能,分布式架构等
    

    1.2 主从复制前提(搭建主从的过程)

    1.2个数据库实例,server_id、server_uuid
    2.主库需要开启二进制日志
    3.主库中建立专用的复制用户(权限是replication slave)
    4.主库全备,类似于“补课”的过程,适用于主库用了很长时间了,需要搭建从库时
    5.change master to 告诉从库—主库的IP、port、user、password、复制的起点
    6.start slave 开启专用的复制线程(主库:binlog_fump_therd、从库:IO_therd、SQL_therd)
    

    1.3 面试题:如何评判主从复制可以替代备份功能

    不能,因为主从复制是基于二进制日志的,如果主库执行了删库的操作,从库也会执行的,所以主从复制不能用于恢复逻辑损坏,适合用物理恢复
    

    第3章 主从复制的工作过程(异步复制)

    3.1 主从复制的工作过程

    1.从库执行change master info时,会把IP、port、user、password、binlog文件名、position号写入msater.info文件中
    2.从库执行start slave时,会立即生成IO线程和SQL线程
    3.从库IO线程会读取master.info文件中的信息,获取主库的IP、port、binlog文件名、position号,连接主库
    4.主库会生成一个专用的dump线程来和从库的IO线程交互
    5.IO线程根据master.info文件中的binlog文件名和position号,去请求主库最新的binlog日志信息
    6.主库的dump线程会去检查binlog的信息,如果有就通过网络传输给IO线程
    7.IO线程会立即将接收过来的binlog信息转存到TCP/IP缓存,并且更新master.info文件中的信息,同时返回ACK给主库表示确认收到了(此时主库的工作完成)
    8.IO线程把TCP/IP缓存中的binlog信息存储到relay-log日志文件.(此时IO线程的工作完成)
    9.SQL线程读取relay-log.info文件中的信息,获取上一次回放relay-log位置信息作为起点,开始回放relay-log
    10.SQL线程回放完成之后,会立即更新relay-log.info文件中的信息(为下一次回放做准备)
    11.从库会自动清理应用过的relay-log
    补充说明:
    主库的dump线程会监控着binlog信息,当有新的binlog生成时,会发送信号给IO线程,IO线程立即发出申请
    

    第4章 主从复制搭建流程

    1.1主从复制前提

    1 两台以上mysql实例 ,server_id,server_uuid不同
    2 主库开启二进制日志
    3 专用的复制用户
    4 保证主从开启之前的某个时间点,从库数据是和主库一致(补课)
    5 告知从库,复制user,passwd,IP port,以及复制起点(change master to)
    6 线程(三个):Dump thread  IO thread  SQL thread 开启(start slave)
    

    1.2环境规划

    # 主库
    ip:10.0.1.25 port:3306 server_id=25
    软件目录 /soft
    数据目录 /data
    二进制日志目录 /data/binlog
    错误日志目录   /data/error
    # 从库
    ip:10.0.1.26 port:3306 server_id=26
    软件目录 /soft
    数据目录 /data
    二进制日志目录 /data/binlog
    错误日志目录   /data/error
    

    1.3 主库的操作

    1.1 创建相应的目录

    mkdir /soft
    mkdir /data/binlog -p
    mkdir /data/error
    

    1.2 编写配置文件

    vim /etc/my.cnf
    #服务端
    [mysqld]
    user=mysql
    #软件安装路劲
    basedir=/soft/mysql5726
    #数据路劲
    datadir=/data/mysql/data
    #服务端socket文件位置
    socket=/tmp/mysql.sock
    #关闭自动提交机制
    autocommit=0
    #服务器ID号
    server_id=25
    #二进制日志
    log_bin=/data/binlog/mysql-bin
    #二进制日志记录模式
    binlog_format=row
    #错误日志路劲
    log_error=/data/error/mysql.log
    log_timestamps=system
    #端口号
    port=3306
    #客户端
    [mysql]
    #客户端socket文件位置
    socket=/tmp/mysql.sock
    

    1.3 启动mysql

    systemctl start mysqld
    

    1.4 从库的操作

    1.1 创建相应的目录

    mkdir /soft
    mkdir /data/binlog -p
    mkdir /data/error
    

    1.2 编写配置文件

    vim /etc/my.cnf
    #服务端
    [mysqld]
    user=mysql
    #软件安装路劲
    basedir=/soft/mysql5726
    #数据路劲
    datadir=/data/mysql/data
    #服务端socket文件位置
    socket=/tmp/mysql.sock
    #服务器ID号
    server_id=26
    #关闭自动提交机制
    autocommit=0
    #二进制日志
    log_bin=/data/binlog/mysql-bin
    #二进制日志记录模式
    binlog_format=row
    #错误日志路劲
    log_error=/data/error/mysql.log
    log_timestamps=system
    #端口号
    port=3306
    #客户端
    [mysql]
    #客户端socket文件位置
    socket=/tmp/mysql.sock
    

    1.3 启动mysql

    systemctl start mysqld
    

    1.5 主库中创建复制用户并授权

    mysql -uroot -p 123
    grant replication slave on *.* to repl@'10.0.1.%' identified by '123';
    select user,host from mysql.user;
    

    1.6 备份主库并恢复到从库(类似于”补课”的过程)

    1.1 主库操作

    mysqldump  -A --master-data=2 --single-transaction  -R -E --triggers >/data/backup/full.sql
    #查看备份文件,查看此时的posation号
    -- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000005', MASTER_LOG_POS=489;
    

    1.2 从库操作

    1. 登录从库 msyql -uroot -p
    把主库的备份数据发到从库/data/backup/
    scp -rp /data/backup/* 10.0.1.26:/data/backup
    2. 把主库的备份数据导入从库
    mysql> set sql_log_bin=0;
    mysql> source /data/backup/full.sql
    mysql> set sql_log_bin=1;
    此时,从库在某个时间点和主库一致了
    

    1.7 告知从库关键复制信息

    1.1 从库操作

    CHANGE MASTER TO
      MASTER_HOST='192.168.114.50',
      MASTER_USER='repl',
      MASTER_PASSWORD='456',
      MASTER_PORT=3306,
      MASTER_LOG_FILE='mysql-bin.000005',
      MASTER_LOG_POS=489,
      MASTER_CONNECT_RETRY=10;
    

    1.8 开启线程

    1.1 从库操作

    mysql>start slave;
    

    1.2 报错

    The slave I/O thread stops because master and slave have equal MySQL server UUIDs; these UUIDs must be different for replication to work.
    原因:因为是直接克隆的第一台,所以在数据目录auto.cof里面的uuid和主库的一样
    

    1.3 解决办法

    mv /data/mysql/auto.cnf /data/mysql/auto.cnf.bak
    关闭MySQL
    systemctl stop mysqld
    启动MySQL
    systemctl start mysqld
    查看主从状态
    show slave status 
    可以看到解决了
    

    1.9 主从中涉及到的文件和线程

    1.1 线程

    1. 主库
    dump_thread
    2. 从库
    IO_thread
    sql_thread
    

    1.2 文件

    1. 主库
    二进制日志文件
    例
    mysql-bin.000002
    2. 从库
    db07-relay-bin.000003    #中继日志
    master.info              #主库信息记录日志           
    relay-log.info           #中继日志应用情况信息
    

    第6章 主从异常

    1.1 主从异常的2大方面

    1. 主从故障
    2. 主从延时
    

    1.2 主从故障

    1.1 IO线程故障

    第一个方面的原因(连接原因)

    常见原因大概一下这些:
    1.	IP不对
    2.	port不对
    3.	复制用户的用户名和密码不对
    4.	防火墙
    5.	达到了连接上限数
    6.	主库没有启动
    原因有很多,有一个办法可以快速定位到具体是哪一个原因
    直接拿复制用户去登录主库,看看会报什么错误
    

    现象一:ip/port/复制用户的用户名和密码不对/主库没有启动的

    密码不对:
    [root@db01 data]# mysql -urepl -p12321321 -h 10.0.0.51 -P 3307
    mysql: [Warning] Using a password on the command line interface can be insecure.
    ERROR 1045 (28000): Access denied for user 'repl'@'db01' (using password: YES)
    用户名不对:
    [root@db01 data]# mysql -urep -p123 -h 10.0.0.51 -P 3307
    mysql: [Warning] Using a password on the command line interface can be insecure.
    ERROR 1045 (28000): Access denied for user 'rep'@'db01' (using password: YES)
    =================================================================================================
    IP地址不对:
    [root@db01 data]# mysql -urepl -p123 -h 10.0.0.52 -P 3307
    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' (113)
    端口不对:
    [root@db01 data]# mysql -urepl -p123 -h 10.0.0.51 -P 3309
    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.51' (111)
    说明:这2个如果不对的话,敲下回车的时候会卡一下,然后出来报错信息
    

    现象二:主库连接数上线限

    show slave  staus G 
    Last_IO_Errno: 1040
    Last_IO_Error: error reconnecting to master 'repl@10.0.0.51:3307' - retry-time: 10  retries: 7
    处理思路:
    拿复制用户,手工连接一下
    [root@db01 ~]# mysql -urepl -p123 -h 10.0.0.51 -P 3307 
    mysql: [Warning] Using a password on the command line interface can be insecure.
    ERROR 1040 (HY000): Too many connections
    处理方法:
    db01 [(none)]>set global max_connections=300;
    

    处理方法

    stop  slave            停止从库所有的线程
    reset slave all        清空master.info里面的信息
    change master to       重新把正确的主库信息写入master.info
    start slave             开启线程
    

    第二个方面的原因(请求和接收二进制原因)

    主库缺失日志
    从库方面,二进制日志位置点不对
    报错现象如下:
    Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'could not find next log; the first event 'mysql-bin.000001' at 154, the last event read from '/data/3307/data/mysql-bin.000002' at 154, the last byte read from '/data/3307/data/mysql-bin.000002' at 154.'
    

    解决办法:

    重新搭建主从
    注意: 在主从复制环境中,严令禁止主库中reset master; 可以选择expire 进行定期清理主库二进制日志
    

    第三个方面的原因(存储binlog到relay-log中)

    这种情况一般是relay-log.info没有写入的权限,把这个文件的权限改一下即可
    1.停止线程
    2.修改权限
    3.启动线程
    

    1.2 SQL线程故障

    1.1 SQL线程故障原因

    1. 主从安装的MySQL版本不同,参数设定不同!比如:数据类型的差异、SQL_MODE的影响
    2. 要创建的数据库对象,已经存在
    3. 要删除或修改的对象不存在
    4. DML语句不符合表定义及约束时和主键冲突
    归根揭底的原因都是由于从库发生了写入操作
    

    1.2 主键冲突问题处理

    报错原因:主键冲突报错
    Last_Error: Could not execute Write_rows event on table yu.fen; Duplicate entry '1' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log mysql-bin.000007, end_log_pos 950
    对于表不是很复杂,最稳妥解决方案
    第一步:把从库里面报主键冲突的那一行找出来
    第二步:再把主库里面这一行主键的对应的值找出来,2者对比
    第三步:然后在从库里面,把这一行值用update 改为和主库的一样
    第四步:在从库里面跳过这个错误(1.stop slave 2. set global sql_slave_skip_counter = 1)
    第五步:重启线程(start slave)
    

    1.3 对于SQL线程出现故障,官方提供了一种以从库为核心的处理方案

    方法一:
    stop slave; 
    set global sql_slave_skip_counter = 1;
    #将同步指针向下移动一个,如果多次不同步,可以重复操作。
    start slave;
    方法二:
    /etc/my.cnf
    slave-skip-errors = 1032,1062,1007
    常见错误代码:
    1007:对象已存在
    1032:无法执行DML
    1062:主键冲突,或约束冲突
    警告:
    以上操作有时是有风险的,最安全的做法就是重新构建主从。把握一个原则,一切以主库为主.
    

    1.4 最好的处理方法

    (1) 可以设置从库只读.=======这种方法基本不用了
    db01 [(none)]>show variables like '%read_only%';
    注意:
    只会影响到普通用户,对管理员用户无效。
    super_read_only  加上这个参数root用户 也无法写入了
    (2)加中间件   =======最推荐使用的方法,即使是管理员也无法对从库进行写入
    读写分离。
    

    1.3 主从延时

    1.1 什么是主从延时

    主库做了操作,从库要比较久的时间才能追上
    

    1.2 外在因素

    1. 网络
    2. 主从硬件差异大
    3. 主从的版本不一致
    4. 主从的参数配置有差异
    

    1.3. 主库方面的原因

    原因1:主库的二进制日志写入不及时

    可以通过参数select @@sync_binlog;  5.7版本此参数默认就是1
    说明:这个参数设置为0.有操作系统来决定什么时候把binlog写入磁盘
         这个参数设置为1,只要事务commit,立即写入磁盘
    

    原因2:在传统的主从复制中,主库的binlog_dump线程,以事件的形式,串行传输binlog(5.6、5.5)

    串行化的好处:不会出现逻辑上的混乱
    由于是串行化的原因
     1. 当主库并发事务量大,主库可以并行执行,但是传送日志的是串行的,所以会导致从库的延时高
     2. 当主库有大事务时,由于是以事件的形式传送的,大事务会阻塞后续所有的事务,归根结底还是串行传送           日志的原因
     =======================================================================================
     解决串行传输日志的方案:
     5.6版本,开启GTID.实现了GC(group commit)机制,可以并行传输日志给IO_T线程
     5.7版本,即使不开GTID,会自动维护匿名的GTID,也能实现GC,但是建议还是手动开启
     解决大事务的方案:
     大事务拆分成多个小事务,可以有效的减少主从延时
    

    1. 4 从库方面的原因

    原因:SQL线程导致的主从延时

    在传统主从复制模式中,从库默认只有一个SQL线程,只能串行回放事务。
    1. 主库并发事务大,从库只能串行回放relay-log 
    2. 主库发生大事务,主库开启了GTID并行传送过来了,由于从库只有一个SQL线程,会一直卡在这里执行这个大事务,    从而阻塞了后续所有的事务
    =====================================================================================
    解决方案:
    对于从库串行回放relay-log
    5.6版本,有了GTID,可以实现多SQL线程,但是只能基于不同库的事务进行并发回放====基于库的回放
    例如:主库有三个库,都发生了事务,传送到从库,这种情况下,从库时可以并发回放的
         如果主库只是在一个库下,并发了事务,传送到从库,从库还是进行串行回放
    5.7版本,有了增强的GTID,在SQL方面,提供了基于逻辑时钟(logical_clock),binlog加入了seq_no机制,真正实现了基于事务级别的并发回放,这种技术我们把它称之为MTS(enhanced multi-threaded slave)
    

    第7章 主从延时的监控

    1.1 监控命令

    show slave  statusG
    Seconds_Behind_Master: 0
    用这种方式不太准确(只显示时间,不知道是主库还是从库)
    

    1.2 主库方面原因的监控

    主库:
    mysql> show master status;
    File                    Position
    mysql-bin.000007      981
    从库:
    show slave statusG
    Master_Log_File: mysql-bin.000007
    Read_Master_Log_Pos: 981
    查看2个号码的大小,如果主库的数值很大,从库的数字很小说明,主库传送的不及时,
    

    1.3 从库方面原因的监控

    1.1 首先查看从库拿了多少日志过来

    Master_Log_File: mysql-bin.000007
    Read_Master_Log_Pos: 981
    

    1.2 在查看从库执行了多少日志

    Relay_Log_File: db01-relay-bin.000012
    Relay_Log_Pos: 320
    

    1.3 查找2者之间的对应关系

    拿过来的是binlog,回放的是relay-log2者可定对不上号,所以要找到它们之间的关系
    Exec_Master_Log_Pos: 981   这个值就是记录relay-log回放的位置信息
    Relay_Log_Space: 1566
    如果Exec_Master_Log_Pos: 981比Read_Master_Log_Pos: 981这个值小很多
    说明是卡在了这个位置,我们就找到这个号码对应的语句在干什么,来分析为什么延时了
    
    学习的进阶之路
  • 相关阅读:
    安装Hive2及配置HiveSever2
    sqoop语句
    Sqoop配置
    IO流的概述
    List集合的简单使用
    包装类
    访问权限修饰符
    接口
    抽象类
    final关键字
  • 原文地址:https://www.cnblogs.com/yufenchi/p/12961554.html
Copyright © 2011-2022 走看看