MySQL 主从复制

1. 介绍  
需要2台及以上节点,通过binlog在从库解析回放实现数据复制同步。

搭建步骤:
https://www.processon.com/mindmap/60813d46e401fd53c7b675cf


2. 传统复制 (Classic)

2.1 复制前提 

a. 准备2个以上MySQL实例
db01 172.16.1.51(内网)
db02 172.16.1.52


b. 【主库】开启binlog日志。
mysql> select @@log_bin;
mysql> select @@log_bin_basename;


c.确保主从环境server_id和server_uuid不同
1)查看
mysql> select @@server_id;
mysql> select @@server_uuid;


2)修改从库server_id为52,主库为51
vim /etc/my.cnf
server_id=52

3)修改从库server_uuid
rm -f /data/3306/data/auto.cnf
/etc/init.d/mysqld restart

4)确保两边都reset master;让环境干净,减少干扰
特别是防止GTID影响


2.2 搭建过程

d.主库创建复制用户并授权
mysql> create user repl@'172.16.1.%' identified with mysql_native_password by '123';
mysql> grant replication slave on *.* to repl@'172.16.1.%';

#replication slave 仅用来复制权限。

e. 同步的数据库版本最好一致(8.0.26)。


f. 从库的数据同步(mysqldump/xtrabackup/clone plugin/停库CP)。
========================================================
  1)主数据库锁表
  mysql> flush table with read lock; ##窗口不能关.
mysql> show master status;
+---------------+----------+--------------+------------------+-------------------+
| File          | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------+----------+--------------+------------------+-------------------+
| binlog.000001 |      677 |              |                  |                   |
+---------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

  2)备份主库
mysqldump -uroot -poldboy123 -A --source-data=2 --single-transaction -R -E --triggers --max_allowed_packet=64M|gzip>/server/backup/master_`date +%F`.sql.gz

  3)主数据库解锁
  mysql> unlock tables;
=================主库操作结束==================

  4)拷贝到从库
  scp /server/backup/master_`date +%F`.sql.gz 10.0.0.52:/tmp
  
  5)从库恢复数据
  gzip -d /tmp/master_`date +%F`.sql.gz
  mysql -uroot -poldboy123   ##如果报错,删除/tmp/master_2021-12-19.sql第一行,--master-data被弃用提示.


  6)【从库】指定连接参数以及位置点
  方法1:
[root@db02 ~]# sed -n '24p' /tmp/master_`date +%F`.sql 
-- CHANGE MASTER TO MASTER_LOG_FILE='binlog.000001', MASTER_LOG_POS=677;

方法2:
binlog.000001 |      677 | 


CHANGE MASTER TO
  MASTER_HOST='172.16.1.51',
  MASTER_USER='repl',
  MASTER_PASSWORD='123',
  MASTER_PORT=3306,
  MASTER_LOG_FILE='binlog.000001',
  MASTER_LOG_POS=677,
  MASTER_CONNECT_RETRY=10;
  
###5.7以前上面的CHANGE MASTER TO语句,写到从库master.info文件里,
5.7及以后写到一张表里(mysql.slave_master_info).

mysql> select * from mysql.slave_master_info\G
*************************** 1. row ***************************
                Number_of_lines: 32
                Master_log_name: binlog.000001
                 Master_log_pos: 677
                           Host: 172.16.1.51
                      User_name: repl
                  User_password: 123
                           Port: 3306
                  Connect_retry: 10

帮助:
help CHANGE MASTER TO


7)从库启动专用复制线程 start slave;
mysql> start slave; ##开启同步开关
mysql> show slave status\G
成功标志:两个Yes
             Slave_IO_Running: Yes
             Slave_SQL_Running: Yes


#MySQL 8.0.22+:命令如下
mysql> START REPLICA;
mysql> SHOW REPLICA STATUS\G
成功标志:两个Yes
          Replica_IO_Running: Yes
          Replica_SQL_Running: Yes
###重启
mysql> stop replica;
mysql> start replica;
mysql> show replica status\G
(over)


2.2 传统主从复制原理
课后作业:自己搞定主从复制原理,并要能表达出来。
面试必问:必会不够,百里挑1

1.5.6两种复制方式

2.在主库开启[binlog日志],然后从库获取主库binlog日志,在从数据库里异步回放来实现的。
  这个过程是[异步]的工作模式.
  
3.复制的时候有3个线程

2.2.1  涉及到的线程
# 主库线程
binlog dump线程,负责投递binlog。
作用: 
    a. 与从库进行交互
    b. 监控binlog的变化
    c. 投递binlog给从库
监控: 
    show processlist;
    ##Binlog Dump | 2164 | Source has sent all binlog to replica; waiting for more updates


# 从库线程
IO线程  : 
    a. 负责连接主库
    b. 和主库的Binlog Dump交互 
    c. 接收和存储主库的binlog日志,存储到从库relay-log(中继日志)中

SQL线程
    a.回放relay-log中的日志应用到从数据库中。
    b.记录回放的位置到relay-log.info中,8.0没有此文件了,而是记录到了表里。

主从状态监控: 
    show slave status \G

    
2.2.2  涉及到的文件
# 主库:  
  binlog:二进制日志。 
  
# 从库:
  relay-log :中继日志,从库用来临时存储接收到的binlog日志。
  master.info: 存放连接主库的信息(ip、port、user、password、已经获取的binlog位置点)
               5.7以上在表中,5.7以前是磁盘上文件。
  relay-log.info:存储SQL线程回放过的日志位置信息。 5.7以上在表中,5.7以前是磁盘上文件。
  

8.0主从复制文件转成表变化: 
原始master.info文件转成了table,mysql.slave_master_info
db02 [(none)]>select * from mysql.slave_master_info\G
*************************** 1. row ***************************
                Number_of_lines: 32
                Master_log_name: mysql-bin.000002
                 Master_log_pos: 156
                           Host: 172.16.1.51
                      User_name: repl
                  User_password: 123
                           Port: 3306
                  Connect_retry: 60

relay-log.info文件转成了table mysql.slave_relay_log_info
db02 [(none)]>select * from mysql.slave_relay_log_info\G
*************************** 1. row ***************************
                             Number_of_lines: 14
                              Relay_log_name: ./db02-relay-bin.000002
                               Relay_log_pos: 1270
                             Master_log_name: mysql-bin.000002
                              Master_log_pos: 1055


原始master.info文件转成了table,mysql.slave_master_info
db02 [(none)]>select * from mysql.slave_master_info\G  ###记录io线程存放binlog位置点
mysql> select * from mysql.slave_master_info\G
*************************** 1. row ***************************
                Number_of_lines: 32
                Master_log_name: binlog.000001  #读取到文件名
                 Master_log_pos: 1216  ##位置点
                           Host: 172.16.1.51
                      User_name: repl
                  User_password: 123
                           Port: 3306
                  Connect_retry: 10

relay-log.info文件转成了table mysql.slave_relay_log_info

mysql> select * from mysql.slave_relay_log_info\G
*************************** 1. row ***************************
                             Number_of_lines: 14
                              Relay_log_name: ./db02-relay-bin.000003 ##回放的文件
                               Relay_log_pos: 240  #回放到数据库的中继日志位置
                             Master_log_name: binlog.000001
                              Master_log_pos: 1216
                                   Sql_delay: 0

2.2.3 画图说明主从复制原理 ******

a. 从库执行change master to 命令,将主库连接信息和binlog位置信息写入master.info文件或者slave_master_info表中
b. 从库执行start slave,启动从库的IO,和SQL线程 
c. IO线程读取主库链接信息,连接主库,主库派生dump线程(dump自动监控binlog变化)
d. IO线程根据binlog位置点信息,获取最新的binlog
e. dump 截取并投递binlog给从库IO线程 ,主库不关心投递的结果。
f. IO线程收到binlog(缓存),立即更新master.info 或者slave_master_info表
g. 缓存binlog数据写入relaylog
h. SQL线程读取relaylog.info或者slave_relay_log_info表,获取到上次回放到的位置点,继续往后回放,回放完成后,再次更新relaylog.info信息
i. 回放过的relaylog,relay_log_purge线程会定期删除这些日志。

2.3 复制监控(ZABBIX写脚本插件)

2.3.1 监控方法: 

a. 自带命令show slave status\G

b. pt-table-checksum(主从数据校验)/pt-table-sync(同步)/pt-heartbeat(监控主从心跳)

pt-heartbeat监控主从
https://baijiahao.baidu.com/s?id=1654616467161901898&wfr=spider&for=pc

c. orch estrator 主从拓扑可视化工具

2.3.2 自带命令 show slave status \G

主从复制状态核心参数:
Slave_IO_Running:  Yes
Slave_SQL_Running: Yes

主从延迟判断方法:
方法1:
Seconds_Behind_Master: 0  #从库更新延迟秒数

方法2:
#更科学方法;主库写时间戳到一张表里,从库读出来和当前从库时间比对,进而确定是否延迟
pt-heartbeat监控主从
https://baijiahao.baidu.com/s?id=1654616467161901898&wfr=spider&for=pc

方法3:看状态中的IO的binlog位置,SQL对应binlog位置,确定延迟的日志量。

# 主库的复制信息
mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for source to send event
                  Master_Host: 172.16.1.51
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 10
              Master_Log_File: binlog.000001
          Read_Master_Log_Pos: 1230
               Relay_Log_File: db02-relay-bin.000002
                Relay_Log_Pos: 874
        Relay_Master_Log_File: binlog.000001
 
# 从库SQL线程已经回放的中继日志信息  
mysql> select * from mysql.slave_relay_log_info\G
                  Relay_log_name: ./db02-relay-bin.000002
                   Relay_log_pos: 874
                 Master_log_name: binlog.000001
                  Master_log_pos: 1230
说明:通过后两条对比master.info,判断主从延时的日志量。


mysql> show replica status\G

# 主从复制线程故障
Slave_IO_Running: Yes
Slave_SQL_Running: Yes

Last_IO_Errno: 0   ##IO故障号码
Last_IO_Error:     ##IO故障提示

Last_SQL_Errno: 0  ##SQL故障号码
Last_SQL_Error:    ##SQL故障提示
            


# 过滤复制相关信息            
Replicate_Do_DB: 
Replicate_Ignore_DB: 
Replicate_Do_Table: 
Replicate_Ignore_Table: 
Replicate_Wild_Do_Table: 
Replicate_Wild_Ignore_Table: 


# 主从之间延时的秒数
Seconds_Behind_Master: 0


# 延时从库状态
SQL_Delay: 0
SQL_Remaining_Delay: NULL
    
    
# GTID 复制    
Retrieved_Gtid_Set: 
Executed_Gtid_Set: 
       


2.4 复制的故障分析及处理
讲解见导图:
https://www.processon.com/mindmap/60813d621e08534b2ef252c1


#  IO线程方面: 
a. 监控 
Slave_IO_Running: Yes
正常状态:Yes
有问题的状态:Connecting、NO

具体问题分析: 
        Last_IO_Errno: 0
        Last_IO_Error: 

IO都干什么活? 
(1) 连接主库 (Connecting )
通信故障:1.防火墙。2.网络。3.IP\PORT\USER\PASSWORD。4.连接数上限
change参数错误处理方法: 
    stop slave; 
    reset slave all;
    select * from mysql.slave_master_info;    
    change master to 
    start slave;
(2) 请求日志,接收日志,落地日志(NO)
reset master; 
修复方式: 
    stop slave; 
    reset slave; 

CHANGE MASTER TO
  MASTER_HOST='172.16.1.51',
  MASTER_USER='repl',
  MASTER_PASSWORD='123',
  MASTER_PORT=3306,
  MASTER_LOG_FILE='binlog.000001',
  MASTER_LOG_POS=1230,
  MASTER_CONNECT_RETRY=10;
  
(3) server_id server_uuid重复
修改为不同即可。


#  SQL线程方面: 
Slave_SQL_Running: Yes
SQL主要工作是什么? 
回放ralay log,执行里面的SQL语句。

其实研究SQL线程故障,就是在研究SQL语句为什么执行不了?
a. 创建的对象(库、表、用户、索引。。。。),从库已经存在了。
b. insert \ update \ delete \alter \drop 从库对象不存在。
c. 约束冲突
d. 配置不兼容(比如不同版本) 


原因: 
    1. 误操作 chang master to 指定位置点不对
    2. 从库被写入了
    3. 业务繁忙时,从库宕机了 
    4. 主从切换时,没有正确操作(锁定原主库+binlog写入)
    5. 双主结构,没有正确使用 

处理原则: 
    1. 一切以主库为准
    2. 双主屏蔽多写。
    3. 从库尽量设置只读

如果出现了怎么处理: 
    1. 冲突操作回退回去
    2. 从库跳过错误(配合pt-checksum/pt-sync)  ###8.0.26
    
    mysql> stop slave;
    mysql> set global sql_slave_skip_counter=1;  ###8.0.26好用
    mysql> start slave;


 

你可能感兴趣的:(mysql,数据库,java)