MySQL主从复制

1,介绍

依赖二进制日志的,实时备份的一个多节点架构

2,主从复制的前提

至少两个实例

不同的server_id

主库需要开启二进制日志

主库需要授权一个专用的复制用户

主库数据备份

开启专用复制线程

 



3,搭建主从复制

3.1准备多实例

参考:https://www.cnblogs.com/dengmeng/articles/12733446.html

3.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"

3.3检查主库(3307)的二进制情况

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

3.4连接主库,创建复制用户

mysql -S /data/3307/mysql.sock

grant replication slave on *.* to repl@'10.0.0.%' identified by '123456';

3.5进行主库数据备份

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

3.6登录从库,恢复数据(3308)

登录:
mysql -S /data/3308/mysql.sock

关闭二进制日志记录:
set sql_log_bin=0;

恢复数据:
source /tmp/full.sql;

3.7在从库填写主库信息

获取模板信息:help change master to;

CHANGE MASTER TO
MASTER_HOST='主库的IP地址',
MASTER_USER='主库的复制用户',
MASTER_PASSWORD='复制用户的密码',
MASTER_PORT=主库的端口号,
MASTER_LOG_FILE='从库起始备份的二进制文件,就是全备里面的二进制文件信息',
MASTER_LOG_POS=备份里面的位置号和二进制文件在一起,
MASTER_CONNECT_RETRY=10;断开连接之后重连次数

列如:

CHANGE MASTER TO
MASTER_HOST='10.0.0.51',
MASTER_USER='repl',
MASTER_PASSWORD='123456',
MASTER_PORT=3307,
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=444,
MASTER_CONNECT_RETRY=10;

3.8启动专用的复制线程

start slave;

3.9如果change master to 信息输入错误,怎么解决?

1.将专用复制线程停掉
stop slave;

2.清除所有信息
reset slave all;

3.重新输入CHANGE MASTER TO信息

4.启动专用复制线程
start slave;

3.9.1查看一下主从复制的状态

mysql> show slave status \G

*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.0.0.51
Master_User: repl
Master_Port: 3307
Connect_Retry: 10
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 444
Relay_Log_File: db01-relay-bin.000002
Relay_Log_Pos: 320
Relay_Master_Log_File: mysql-bin.000001
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:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 444
Relay_Log_Space: 526
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 7
Master_UUID: f409df1d-1203-11eb-9bd6-000c29347872
Master_Info_File: /data/3308/data/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.00 sec)

 3.9.2  show slave status 字段详细介绍

1.主库的信息(master.info)
Master_Host: 10.0.0.51 主库的IP Master_User: repl 复制用户名 Master_Port: 3307 主库的端口号 Connect_Retry: 10 断链之后重试次数 Master_Log_File: mysql-bin.000001 已经获取到的binlog文件名 Read_Master_Log_Pos: 444 已经获取到的binlog位置号
2.从库的relaylog信息(relay-log.info)
Relay_Log_File: db01-relay-bin.000002从库已经运行过的relaylog文件名
Relay_Log_Pos: 320 从库已经运行过的relaylog位置点

3.从库复制线程工作状态
Slave_IO_Running: Yes
Slave_SQL_Running: Yes

4.过滤复制相关的状态
Replicate_Do_DB: 
Replicate_Ignore_DB: 
Replicate_Do_Table: 
Replicate_Ignore_Table: 
Replicate_Wild_Do_Table: 
Replicate_Wild_Ignore_Table:

5.从库延时主库的时间(单位/S)
Seconds_Behind_Master: 0

6.从库线程报错详细信息
Last_IO_Errno: 0 IO报错的号码
Last_IO_Error: IO报错的具体信息
Last_SQL_Errno: 0 SQL报错的号码
Last_SQL_Error: SQL线程报错的具体原因

7.延时从库
SQL_Delay: 0 延时从库设定的时间
SQL_Remaining_Delay: NULL 延时操作的剩余时间

8.GTID复制信息
Retrieved_Gtid_Set:  接收到的GTID的个数
Executed_Gtid_Set:  执行了GTID的个数

 



4,主从复制工作过程(原理)

4.1名词认识

4.1.1 文件

主库:
binlog

从库:
relay-log:中继日志   
master.info:主库信息文件
relay-log.info:中继日志应用信息

4.1.2 线程

主库:
binglog_dump_therad:二进制日志投递的线程
mysql -S /data/3307/mysql.sock -e "show processlist"   查看二进制投递线程的方法

从库:
IO_Thread:从库的IO线程,请求和接收
binlog SQL_Thread:从库的SQL线程,回放日志

4.2主从复制工作过程说明:

1.从库执行CHANGE MASTER TO的语句,会立即将主库的信息记录到master.info中

2.从库执行start slave,会立即启动IO_thread和SQL_thread两个线程

3.IO_T读取Master.info文件,获取到主库的信息

4.IO_T连接主库,主库会立即分配一个dump_T,进行交互

5.IO_T根据master.info binlog信息,向dunp_T请求最新的binlog

6.主库dump_T经过查询,如果发现有新的binlog,截取并返回给从库的IO_T

7.从库的IO_T会收到binlog,存储在TCP/IP的缓存中(内存),在网络底层返回ACK

8.从库的IO_T会更新master.info信息,重置binlog位置点信息

9.从库的IO_T会将binlog,写入到relay-log中

10.从库SQL_T读取relay-log.info 文件,获取上次的位置点

11.SQL_T按照位置点往下执行relay-log日志

12.SQL_T执行完成后,重新更新relay-log.info

13.在mysql引擎层面有一个pager线程,将应用过的relay-log做一下清理

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

 



5,主从复制监控及故障处理

5.1主从监控

5.1.1 主库:

show processlist;

5.1.2 从库:

show slave status\G

5.2 主从复制故障分析及处理

从库线程复制状态:

Slave_IO_Running: Yes
Slave_SQL_Running: Yes

从库线程报错详细信息:

Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:

5.3 IO线程故障

(1)链接主库连接不上:Slave_IO_Running:connecting


原  因 :网络不通 ,防火墙问题,IP,prot,user,passwd不对,skip_name_resolve,连接数上限

处理思路:msyql -u -p -h -P 手动链接测试一下

如何处理:

1.将专用复制线程停掉
stop slave;

2.清除所有信息
reset slave all;

3.重新输入CHANGE MASTER TO信息

4.启动专用复制线程
start slave;

(2)IO线程NO的状态分析:Slave_IO_Running:NO

原因一:日志名不对

解决方法:对比备份文件的master_log_file

原因二:日志损坏,日志不连续

原因三:server_ID 重复

(3)写relaylog

(4)更新master.info

 

5.4 SQL线程故障

SQL线程主要做三件事:
读relay-log.info
读relay-log,并执行SQL
更新relay-log.info

以上文件损坏,最好是重新构建主从

如果SQL语句执行不成功,版本差异导致,主从参数不一致,改变不存在的对象,DML语句不符合表的定义及约束时

解决方法:

方法一:跳过当前的错误点

stop slave;

set global sql_slave_skip_counter=1; 

方法二:跳过错误代码

/etc/my.cnf

slave-skip-errors=1032,1062,1007

方法三:推荐使用

设置从库为只读,防止写入

使用我们的中间件做成读写分离的架构

 

5.5主从延时原因分析

Seconds_Behind_Master: 0:从库延时主库的时间(单位/S)

5.5.1主库方面:

日志写入不及时

解决方法:双一标准之一

5.6版本以后默认是开启的,=1会将binlog立即刷写到磁盘

mysql> select @@sync_binlog;
+---------------+
| @@sync_binlog |
+---------------+
|             1 |
+---------------+

主库并发业务较高

分布式架构

从库太多

级联主从

对于classic replication:

主库是有能力并发运行事务的,但是在dump_T在传输日志的时候,是以事件为单元传输日志的,所以导致事务的传输工作是串行方式的,这时在主库的TPS很高时,会产生比较大主从延时

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

5.5.2从库方面:

classic replication:

SQL线程只有一个,所以说只能串执行relay的事务

怎么解决:加线程,在5.6中出现了database级别的多线程SQL,只能针对不同库下的事务进行并发处理,在5.7版本加入MTS,才真正实现了事务级别的并发SQL

 6.延时从库

作用:延时从库是为了防止数据逻辑损坏

物理损坏:磁盘出现故障,误删除了frm文件

逻辑损坏:drop库或表

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

6.1设计理念

对SQL线程进行延时设置,一般设置的时间是3-6小时

6.2如何设置

在从库去设置延时时间
stop slave; CHANGE MASTER TO MASTER_DELAY
=300; start slave;

6.3 如何使用延时从库,当主库发生故障如何使用从库代替主库,解决问题思路流程;

1.停止SQL线程,停止主库业务
stop slave sql_thread;
2.模拟SQL手工恢复relaylog到drop之前的位置点 3.截取relaylog日志,找到起点(relay-log.info)和终点(drop操作之前的位置点)
mysql> show slave status\G 这条命令使用找到relaylog的起点
mysql> show relaylog events in 'db01-relay-bin.000002'                 drop前位置点
4.获取截取的日志,验证数据可用性

 



 

7.过滤复制

主库(从主库方面控制的话,将以下两个参数写入到my.cnf,用的不多,简单了解)

show master status; (查看当前的一个状态)

binlog_do_db :白名单(添加白名单的库,记录binlog) binlog_ignore_db:黑名单(添加黑名单的库,排除不记录binlog)

从库(在SQL线程回访日志时,进行控制过滤)

show slave status \G(查看从库当前黑白名单状态)

replicate_do_db: (白名单,只会复制那些库)
replicate_ignore_db:(黑名单,排除那些库不复制)


replicate_do_table: (白名单,只会复制那些表)
replicate_ignore_table:(黑名单,排除那些表不复制)


replicate_wild_do_table: (白名单,模糊匹配表)
replicate_wild_ignore_table:(黑名单,模糊匹配表)

如何配置:将对应的参数配置在my.cnf,重启一下数据就可以了

8.半同步复制

和传统复制的区别:以一个插件形式提供的功能

主库方面多了一个线程:ACK_receive

从库方面多了一个线程:ACK _send

主库的ACK_receive线程只有接收到从库发来的ACK确认,主库事务才能commit成功

从库的ack_send只有等relay_log记录到磁盘上才会发送ACK给主库

主库只会等待10s,如果ACK还没收到,就会自动替换为异步复制
posted @ 2020-10-19 22:13  鄧萌  阅读(152)  评论(0)    收藏  举报