第八章 主从复制 - 基础篇

企业高可用性标准

非计划内故障停机

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    金融级别

企业级高可用方案

负载均衡: 有一定的高可用性 
- LVS
- Nginx

主备系统: 有高可用性,但是需要切换,是单活的架构
- KeepAlive  
-  MMM        
-  MHA  主流

真正高可用: 多活系统
- NDB Cluster  (MySQL集群版)
- Oracle RAC  (金融)
- Sysbase cluster 
- **PXC** 
- **MGC**
- <font color=red>**InnoDB Cluster  (MGR 5.7.17)**</font>

主从复制简介

1) 基于二进制日志复制的
2) 主库的修改操作会记录二进制日志
3) 从库会请求新的二进制日志并回放,最终达到主从数据同步
4) 主从复制核心功能:
​- 辅助备份,处理物理损坏

  • 扩展新型的架构:高可用,高性能,分布式架构等

主从复制的前提

1)多节点,至少2个数据库实例
2)server_id 必须且唯一,uuid 唯一,主库要开启binlog
3)主库需要一个专门用作复制的用户 (replication slave)
4) 通过备份将源库数据补偿到从库
5)告知从库:复制使用的 用户,密码,IP,port,复制的文件和起点
6)需要专门的复制线程 (start slave)

主从复制部署

环境说明

使用了一台虚拟机,做了多实例.
mysql3307   端口 3307
mysql3308   端口 3308

准备多实例环境

systemctl start mysqld3307.service
systemctl start mysqld3308.service
mysql -S /data/3307/mysql.sock
mysql -S /data/3307/mysql.sock

检查主库binlog,server_id

-- 3307实例操作
mysql[(none)]>select @@log_bin;
mysql[(none)]>select @@server_id;

主库创建复制用户

# 3307实例操作
mysql[(none)]>grant replication slave on *.* to repl@'10.0.0.%' identifieed by '123456';

# 查看用户是否创建成功
mysql[(none)]>select user,host from mysql.user where user='repl';

通过备份将源库数据补偿到从库

# 主库备份
mysqldump  -S /data/3307/mysql.sock -A  -R -E --triggers --master-data=2 --single-transaction --max-allowed-packet=128M   >/tmp/full.sql
# 从库恢复
mysql -S /data/3308/mysql.sock </tmp/full.sql

告知从库,用户名,密码,IP ,port,自动复制的起点

# 登录从库
mysql -S /data/3308/mysql.sock

# 告知从库关键复制信息(登录从库执行)、3308
CHANGE MASTER TO
  MASTER_HOST='10.0.0.51',
  MASTER_USER='repl',
  MASTER_PASSWORD='123456',
  MASTER_PORT=3307,
  MASTER_LOG_FILE='mysql-bin.000009',
  MASTER_LOG_POS=444,
  MASTER_CONNECT_RETRY=10;

帮助与参数说明

获取主/从数据库通讯命令: help change master to

命令参数说明:
CHANGE MASTER TO
  MASTER_HOST='10.0.0.51',  --> 主库的IP
  MASTER_USER='repl',       --> 主库复制用户
  MASTER_PASSWORD='123456',  --> 主库复制用户密码
  MASTER_PORT=3307,         --> 连接主库的端口
  MASTER_LOG_FILE='mysql-bin.000006',   --> 需要复制的二进制日志名
  MASTER_LOG_POS=444,       --> 需要复制的二进制日志起始位置
  MASTER_CONNECT_RETRY=10;

启动线程

# 开启从库线程、3308实例操作
mysql[(none)]>start slave;

检查主从状态

mysql -S /data/3308/mysql.sock -e "show slave status\G"|grep 'Yes'

--- 显示一下代表成功
 Slave_IO_Running: Yes
 Slave_SQL_Running: Yes     

简单排错过程

mysql -S /data/3308/mysql.sock -e "show slave status \G;"|grep "Last" 

主从复制原理

主从复制过程中涉及到的文件

主库:

  • binlog -- 记录主库的数据变化

从库:

  • relaylog -- 中继日志,临时存储日志信息的文件
  • master.info -- 信息文件,保存master的相关信息
  • relay-log.info -- 信息文件,记录上次SQL线程执行过的relaylog的位置点

主从复制中涉及到的线程

Master 与 Slave 之间实现整个主从复制的过程是由三个线程参与完成的。
主库(Master) :

  • Binlog_dump_Thread

    投递线程,主库发送二进制日志给从库的线程
    查看:show processlist;

从库(Slave) :

  • Slave_IO_Thread

    请求binlog,接受binlog的线程

  • Slave_SQL_Thread

    执行 relaylog 日志的线程

主从复制原理

1)change master to 时,ip pot user password binlog position写入到master.info进行记录
2)start slave 时,从库会启动IO线程和SQL线程
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将缓存中的数据,存储到relay-log日志文件,更新master.info文件binlog 文件名和postion,工作完成
9)SQL_T读取relay-log.info文件,获取到上次执行到的relay-log的位置,作为起点,回放relay-log
10)SQL_T回放完成之后,会更新relay-log.info文件。
11)relay-log会有自动清理的功能。
补充1: relay-log会自动被定时清理
补充2: 主库一旦有新的binlog更新,dump会有信号通知,告知IO线程来取新的,来保证复制实时性.

主从复制的监控

从库:

线程状态

[root@db01 ~]# mysql -S /data/3308/mysql.sock -e "show slave status \G"|grep "Running:"
Slave_IO_Running: Yes
Slave_SQL_Running: Yes

线程报错具体信息

[root@db01 ~]# mysql -S /data/3308/mysql.sock -e "show slave status \G"|grep "Last"
Last_Errno: 0
Last_Error: 
Last_IO_Errno: 0
Last_IO_Error: 
Last_SQL_Errno: 0
Last_SQL_Error: 
Last_IO_Error_Timestamp: 
Last_SQL_Error_Timestamp: 

查看主库连接信息有关

[root@db01 ~]# mysql -S /data/3308/mysql.sock -e "show slave status \G"|grep "Master"
Master_Host: 10.0.0.51
Master_User: repl
Master_Port: 3307
Master_Log_File: mysql-bin.000012
Read_Master_Log_Pos: 154
Relay_Master_Log_File: mysql-bin.000012
Exec_Master_Log_Pos: 154

从库和主库延时的时间

[root@db01 ~] mysql -S /data/3308/mysql.sock -e "show slave status \G"|grep "Seconds_Behind_Master"

过滤复制相关状态

[root@db01 ~]# mysql -S /data/3308/mysql.sock -e "show slave status \G"|grep " Replicate_"
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
  Replicate_Ignore_Server_Ids: 
         Replicate_Rewrite_DB: 

延时从库的状态信息

[root@db01 ~]# mysql -S /data/3308/mysql.sock -e "show slave status \G"|grep "Delay:"
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL

监控Gtid复制状态信息

[root@db01 ~]# mysql -S /data/3308/mysql.sock -e "show slave status \G"|grep "Gtid"
           Retrieved_Gtid_Set: 
            Executed_Gtid_Set: 

中继日志监控

[root@db01 ~]# mysql -S /data/3308/mysql.sock -e "show slave status \G"|grep "Relay"
               Relay_Log_File: db01-relay-bin.000005
                Relay_Log_Pos: 367
        Relay_Master_Log_File: mysql-bin.000012
              Relay_Log_Space: 739

主从复制故障

IO线程

(1)读取master.info
​        损坏
​        信息错误: change master to 信息错误
(2)连接主库
        网络
        防火墙
        主机/主库没启动
        连接数上限
(3)请求日志
​        master.info 复制起点
​        主库:损坏,误删除等
(4)接收日志
​        relaylog 损坏
(5)更新master.info

解决方法:

通过复制用户,手工连接主库,查看报错信息
> stop slave 
> reset slave all;
> change master to
> start slave

SQL线程故障 *****

relay.info
回访 relaylog 中的日志 *

SQL语句无法解析

  • 语法,SQL_Mode。版本差异,sql_mode不一致
  • DDL DCL 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:主键冲突,或约束冲突

防止从库写入(以从库为核心的方案)

(1) 可以设置从库只读.
db01 [(none)]>show variables like '%read_only%';
注意:只会影响到普通用户,对管理员用户无效。

(2)加中间件
读写分离。

主从延时

主从延时简介

主库做的事,从库很久才执行

主从延时的现象

最直观:主库做变更,从库看数据状态
Seconds_Behind_Master: 0 (只能证明,有或者没有)
计算日志的差异 ※

主从延时的原因

外部原因

  • 网络,硬件
  • 主库繁忙
  • 版本差异
  • 参数差异

内部因素

主库:

(1) 二进制日志方面
    二进制日志落地不及时
    解决方案:
        - sync_binlog=1
        可以将binlog 单独存放高性能存储中
(2) dump_T(线程) - 默认串行工作模式
    主库的事务量大
    主库发生大事务
    解决方案:
        1. GTID 模式
        2. 双1的保证

如何监控:
    主库: show master status;
    从库:show  slave status\G

从库:

(1) IO 线程方面
    relaylog写入
    解决方案:
    可以将relaylog单独存放高性能存储中
    | relay_log_basename        | /data/3308/data/db01-relay-bin       |
    | relay_log_index           | /data/3308/data/db01-relay-bin.index |

(2) SQL线程方面(只有一个,串行回放)
    默认SQL线程,只能逐条的回放SQL
    事务并发高
    大事务

5.6 版本 加入了多SQL复制 
  按照库(database)级别,进行并发回放SQL
  slave_parallel_workers=16
  slave_parallel_type=DATABASE

5.7 版本 进行了多SQL复制加强(MTS)
  真正按照事务级别,实现了多SQL线程回放
  slave_parallel_workers=16
  slave_parallel_type=logical_clock

注意:必须依赖于 GTID复制 

如何监控 : 
(1) 监控取了多少日志 
    show slave status \G
    Master_Log_File: mysql-bin.000001
    Read_Master_Log_Pos: 1084

(2) 回放了多少日志
[root@db01 /data/3308/data]# cat relay-log.info 
  7
  ./db01-relay-bin.000003
  920
  mysql-bin.000001
  1084

猜你喜欢

转载自www.cnblogs.com/lpcsf/p/12077262.html