Mysql主从复制

MySQL Replication

主从复制介绍

1.主从复制基于binlog来实现的
2.主库发生新的操作,都会记录binlog
3.从库取得主库的binlog进行回放
4.主从复制的过程时异步

搭建主从复制

1.2个或以上的数据库实例
2.主库需要开启二进制日志
3.server_id要不同,区分不同的节点
4.主库需要建立专用的复制用户(replication slave)
5.人为告诉从库一些复制信息(ip,port user pass,二进制日志起点)
6.从库应该开启专门的复制线程

准备多实例

3307为主库 3308位从库 (搭建过程https://www.jianshu.com/writer#/notebooks/40881420/notes/57340778

启动3307

pkill mysqld
systemctl start mysqld 3307

初始化3308

mysqld --initialize-insecure --user=mysql --basedir=/application/mysql --datadir=/data/3308/data
systemctl start mysqld3308
mysql -S /data/3308/mysql.sock

检查3307

mysql -uroot -p123456 -S /data/3307/mysql.sock -e 'select @@port'

检查配置文件
主库:二进制日志是否开启

3307
[mysqld]
basedir=/application/mysql
datadir=/data/3307/data
socket=/data/3307/mysql.sock
port=3307
server_id=7
log_bin=/data/3307/mysql-bin

3308
[mysqld]
basedir=/application/mysql
datadir=/data/3308/data
socket=/data/3308/mysql.sock
port=3308
server_id=8
log_bin=/data/3308/mysql-bin

主库创建复制用户

mysql -uroot -p123456 -S /data/3307/mysql.sock -e "grant replication slave on *.* to repl@'10.0.0.%' identified by '123456';" 

主库进行全备

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

从库

mysql -uroot -p123456 -S /tmp/full.sql
set sql_log_bin=0;
source /tmp/full.sql

告诉从库复制信息

查看起始点
more /tmp/full.sql
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000003', MASTER_LOG_POS=444;
登陆数据库
mysql -uroot -p123456 -S /data/3308/mysql.scok
CHANGE MASTER TO
MASTER_HOST='10.0.0.51',   #主机IP或主机名
MASTER_USER='repl',          #用户
MASTER_PASSWORD='123456',   #密码
MASTER_PORT=3307,      #端口
MASTER_LOG_FILE='mysql-bin.000003',  #binlog日志
MASTER_LOG_POS=444,  #起点
MASTER_CONNECT_RETRY=10;

从库开启复制线程(IO,SQL)

start slave;

检查主从复制的状态

show status slave \G
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
主库创建一个数据库
create database hahaha;
从库检查
show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| backup             |
| binlog             |
| gtid               |
| hahaha             |
| mysql              |
| performance_schema |
| school             |
| sky                |
| sys                |
| test               |
| world              |
| zabbix             |
+--------------------+

如果复制中出现错误看看是否change master to里写错了

stop slave;
reset slave all;
再次change master to...

主从复制的原理

主从复制中涉及的文件

主库:
binlog
从库:
relaylog 中继日志
master.info 主库信息文件
relaylog.info relaylog应用的信息

主从复制中涉及的线程
主库:
binlog_dump Therad : DUMP_T
从库:
SLAVE_IO_THREAD : IO_T
SLAVE_SQL_THREAD : SQL_T

Mysql主从复制_第1张图片
image.png

1.从库执行change master to命令(主库的连接信息+复制点)
2.从库将以上信息,记录到master.info文件中
3.从库执行start slave 命令,立即开启IO_T和SQL_T

  1. 从库的IO_T,读取master.info文件中的信息(IP,PROT,USER,PASS,binlog
    位置点)
    5.从库IO_T请求连接主库,主库专门提供一个DUMP_T,负责和IO_T交互
    6.IO_T根据binlog的位置信息,请求主库新的binlog
    7.主库DUMP_T 将最新的binlog,通过网络TP(传送)给从库的IO_T
    8.IO_T接收到新的binlog日志,存储到TCP/IP缓存中,立即返回ACK给主库,并更新master.info
    9.IO_T将TCP/IP缓存中数据,转存到磁盘relaylog中
    10.SQL_T读取relay.info中的信息,获取上次已经应用过的relay.log的位置信息
    11.SQL_T会按照上次的位置点往后回放最新的relaylog,再次更新relay.info信息
    12.从库会自动purge应用过relay进行定期清理
    补充说明:
    一旦主从复制构建成功,主库当中发生了新的变化,都会通过dump_T发送信号给IO_T,增强了主从复制的实时性

主从复制监控

show slave status\G
mysql> show slave status \G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event   
[主库相关信息 master.info]
                  Master_Host: 10.0.0.51   地址
                  Master_User: repl   用户
                  Master_Port: 3307   端口
                Connect_Retry: 10   尝试几次
              Master_Log_File: mysql-bin.000003   应该与主库相同
          Read_Master_Log_Pos: 609

 [从库relaylog应用信息relay.info]
               Relay_Log_File: db01-relay-bin.000002   从库SQL_T到那个点
                Relay_Log_Pos: 485
        Relay_Master_Log_File: mysql-bin.000003

[从库线程运行状态用于排错]
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
               Last_IO_Errno: 0   从下面复制过来的
                Last_IO_Error: 
               Last_SQL_Errno: 0
               Last_SQL_Error: 

[过滤复制有关的]
              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: 
   Auto_Position: 0
       

主从复制故障

从库:
IO线程故障

连接主库(connecting): 网络,连接信息错误或变更了,防火墙,连接数上限
排查思路:使用复制用户手工登陆,是否用户名 密码 端口 是否正确

stop slave
reset slave all;
change master to...
start slave;

请求binlog
binlog 没开
binlog 损坏,不存在,reset master
主库reset master处理办法
从库
stop slave;
reset slave all;
change master to 最新的
start slave;

SQL线程故障
relay-log损坏
回放relaylog,一下容易出现SQL故障的
insert delete update ----> t1 表不存在,
create table sky --->sky 库不存在
约束冲突(主建,唯一键,非空...)
合理解决办法:
一切以主库为准进行解决
如果出现问题,尽量进行反操作
最直接稳妥的办法,重新构造主从

暴力的解决办法
方法一:

stop slave;
set gloabl sql_slave_skip_counter =1;
将同步指针向下移动一个,如果多次不同步,可以重复操作
start slave;

方法二:

/etc/my.cnf
slvae-skip-errors=1032,1062,1007
常见错误代码
1007:对象已经存在
1032:无法执行DML
1062:主建冲突,或约束冲突

但是,以上操作有时是由风险的,最安全的做法就是重新构造主从
对于主建冲突问题

主从延迟

主库方面
1,binlog写入不及时
sync_binlog=1 及时写入
2,默认情况下dump_T 是串行传输binlog
在并发事务量大时,由于dump_t是串行工作的,导致传输日志较慢
解决办法
必须GTID,使用group commit方式,支持dump_t并行
3.主库及其繁忙
慢语句
锁等待
从库个数
网络延时
从库方面
1.传统复制中
如果主库并发事务量很大,或者出现大事务
由于从库是单线程,导致,不管传的日志有多少,只能一次执行一个事务
5.6版本,有了GTID,可以实现多sql线程,但是只能基于不同库的事务进行并发回放(database)
5.7版本,有了增强的GTID,增加了seq_no,增加了新型的并发SQL线程模式(logical_clock),MTS技术
2.主从硬件差异太大
3.主从的参数配置
4.从库和主库的索引不一致
5.主从版本不一样

监控主从延迟

mysql> show slave status\G
Seconds_Behind_Master: 0
主库方面的原因监控

show master status\G
            File: mysql-bin.000003
         Position: 609
跟从库对比
 Master_Log_File: mysql-bin.000003
          Read_Master_Log_Pos: 609

从库方面的原因监控

cat relay-log.info 
7
./db01-relay-bin.000003
320
mysql-bin.000003
609

show slave status\G
 Relay_Log_File: db01-relay-bin.000004
                Relay_Log_Pos: 320
Exec_Master_Log_Pos: 609
 Master_Log_File: mysql-bin.000003
          Read_Master_Log_Pos: 609
一致没有延迟,如果有区别,查了多少pos 看看谁导致的,查看 exec_masetr_log_pos 与read_master_log_pos查了多少个,查看日志

延时从库

stop slave;
#秒单位
change master to master_delay=300;
start slave;

查看状态

show slave status \G
                    SQL_Delay: 300  #300秒
          SQL_Remaining_Delay: NULL  #最近一个事务还差多少秒
在主库创建一个库
create database aa;
这个时候再去查看
show slave status\G
                    SQL_Delay: 300
          SQL_Remaining_Delay: 294

假如主库被删除了 ,停掉sql线程

故障恢复思路
1.监控到数据库逻辑故障
2.停从库SQL线程,记录已经回放的位置点(截取日志起点)
stop slave sql_thread;
show slave status \G
relay_log_file: db01-relay-bin.000003
relay_log_pos: 320
3.截取relayLog
起点:
show slave status \G
relay_log_file relay_log_pos
终点:drop之前的位置点
show relaylog events in ' '
进行截取
4.模拟sql线程回放日志
从库 source
5.恢复业务
情况一:就一个库的话,从库代替主库工作
情况二:从库导出故障库,还原到主库中

故障演练

主库

create database delay charset utf8mb4;
use delay;
create table t1 (id int);
insert into t1 values(1),(2),(3);
commit;
drop databases delay;

从库

停止从库SQL线程
stop slave sql_thread;
获取起点位置
show slave statu \G
Relay_Log_File: db01-relay-bin.000003
Relay_Log_Pos: 320
找到relay的截取终点
mysql> show relaylog events in 'db01-relay-bin.000003';
+-----------------------+-----+----------------+-----------+-------------+---------------------------------------+
| Log_name              | Pos | Event_type     | Server_id | End_log_pos | Info                                  |
+-----------------------+-----+----------------+-----------+-------------+---------------------------------------+
| db01-relay-bin.000003 |   4 | Format_desc    |         8 |         123 | Server ver: 5.7.26-log, Binlog ver: 4 |
| db01-relay-bin.000003 | 123 | Previous_gtids |         8 |         154 |                                       |
| db01-relay-bin.000003 | 154 | Rotate         |         7 |           0 | mysql-bin.000003;pos=765              |
| db01-relay-bin.000003 | 201 | Format_desc    |         7 |           0 | Server ver: 5.7.26-log, Binlog ver: 4 |
| db01-relay-bin.000003 | 320 | Anonymous_Gtid |         7 |         830 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'  |
| db01-relay-bin.000003 | 385 | Query          |         7 |         943 | create database delay charset utf8mb4 |
| db01-relay-bin.000003 | 498 | Anonymous_Gtid |         7 |        1008 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'  |
| db01-relay-bin.000003 | 563 | Query          |         7 |        1108 | use `delay`; create table t1 (id int) |
| db01-relay-bin.000003 | 663 | Anonymous_Gtid |         7 |        1173 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'  |
| db01-relay-bin.000003 | 728 | Query          |         7 |        1246 | BEGIN                                 |
| db01-relay-bin.000003 | 801 | Table_map      |         7 |        1292 | table_id: 255 (delay.t1)              |
| db01-relay-bin.000003 | 847 | Write_rows     |         7 |        1342 | table_id: 255 flags: STMT_END_F       |
| db01-relay-bin.000003 | 897 | Xid            |         7 |        1373 | COMMIT /* xid=2891 */                 |
| db01-relay-bin.000003 | 928 | Anonymous_Gtid |         7 |        1438 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'  |
| db01-relay-bin.000003 | 993 | Query          |         7 |        1533 | drop database delay                   |
+-----------------------+-----+----------------+-----------+-------------+---------------------------------------+
15 rows in set (0.00 sec)

|db01-relay-bin.000003 | 993 | Query          |         7 |        1533 | drop database delay              这个就是结束位置

截取relaylog

cd /data/3308/data/
截取
mysqlbinlog --start-position=320 --stop-position=993 db01-relay-bin.000003 >/tmp/relay.sql
查看一下relay.sql有没有drop命令 没有就对了

恢复relay到从库

set sql_log_bin=0;
source /tmp/relay.sql
show databases;
show tables;
+-----------------+
| Tables_in_delay |
+-----------------+
| t1              |
+-----------------+
1 row in set (0.00 sec)

过滤复制

快速恢复测试环境
从库

drop database delau;
stop slave;
reset slave all;

主库

reset master;

从库重新连接

mysql> 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=154,
    -> master_connect_retry=10;
Query OK, 0 rows affected, 2 warnings (0.00 sec)
 start slave;

参数
主库(很少用)
binlog_do_db=word 白名单 只会同步word
binlog_ignore_db=word 黑名单 不会同步world
从库(写到配置文件里全是小写)
[库级别的]
replicate_do_db=白名单
replicate_ignore_db:=黑名单
[表级别的]
Replicate_Do_Table:
Replicate_Ignore_Table:
[模糊匹配表]
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:

测试
从库

replicate_do_db=repl
systemctl restart mysqld3308

主库

create database aaaaaaaaaa;

从库查看

show databases;
并没有

主库

create database repl;

从库查看

show databases;

主从调优

5.7从库多线程MTS
必须开启GTID
binlog必须是row模式

gtid_mode=on
enforce_gtid_consistency=on
log_slave_updates=on
slave_parallel_type=LOGICAL_CLOCK
slave_parallel_workers=16
CPU核心数作为标准
master_info_repository=TABLE
relay_log_info_repository=TABLE
relay_log_recovery=ON

你可能感兴趣的:(Mysql主从复制)