前言

主从复制:两台或者更多的数据库实例,通过二进制日志,实现数据同步。为什么需要主从复制,主从复制的作用是什么,答:为了预防灾难。

搭建

第一步:准备多实例环境。如何创建多实例见:

第二步:确保每一个实例的server_id 不同。

检查各自实例图中(my.cnf)的配置是否不同。

第三步:主库检查binlog 是否开启

第四步:主库创建复制用户

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

第五步:主库和从库在主从之前要保证数据结构一致。

主库备份,恢复到从库:https://www.cnblogs.com/jssj/p/13514597.html

第六步:主从连接(重点)

从库中执行以下语句,告知从库连接信息,同步开始点等(我这里有两个从库就两个从库都登入执行)

CHANGE MASTER TO
MASTER_HOST='127.0.0.1', -- 主库ip
MASTER_USER='repl', -- 主从专用用户
MASTER_PASSWORD='repl', -- 用户密码
MASTER_PORT=3307, -- 主库ip
MASTER_LOG_FILE='mysql-bin.000001', --复制开始点的binlog文件
MASTER_LOG_POS=653, --binlog 文件中的开始点
MASTER_CONNECT_RETRY=10; -- 重连次数
MASTER_DELAY = 300; -- 从库SQL线程延时时间设置,(一般一主二从的时候,一从不加延时,一从加延时,这样逻辑误操作可以及时修复)

第七步:从库中启动专用主从线程

start slave ;      -- 启动主从
stop slave;     -- 关闭主从

扩展:

start slave sql_thread  -- 单独启动从库sql线程
start slave io_thread -- 单独启动从库I/O线程
stop slave sql_thread -- 单独停从库sql线程
stop slave io_thread -- 单独停从库I/O线程

第八步:验证主从复制是否正常

查看从库线程

mysql -uroot -S /usr/local/mysql/data/3308/mysql.sock -e "show slave status\G | grep Running"

还有就是在主库上创建数据库,创建表等操作,看看从库是否和主库一致。

如果搭建失败:

执行:(没有问题别执行),然后重新执行以上步骤。  reset slave all  表示重置主从配置信息。

mysql -uroot -S /usr/local/mysql/data/3308/mysql.sock -e "stop slave; reset slave all;"

好了,到这里我们已经搭建完毕。

原理

文件部分

从库文件(以下文件都默认放在数据文件目录下):

主机名-relay-bin.000001      -- 默认叫这个名字,从主库接收到的binlog信息记录在这里

主机名-relay-bin.000002      -- 默认叫这个名字,从主库接收到的binlog信息记录在这里

主机名-relay-bin.index          -- 默认叫这个名字,从主库接收到的binlog信息记录在这里

master.info                            --从库的配置信息: CHANGE MASTER TO ... 的信息。

relay-log.info                         --存储接收的binlog

mysql> select @@master_info_repository;     -- 设置从库配置信息存放的方式:文件/表

mysql> select @@relay_log_info_repository;    -- relay-log存放方式:文件/表,默认文件

mysql> select @@relay_log_purge;      -- relay_log是否开启删除已经被使用过的relay_log

主库文件就是binlog 已经再之前文档讲过,这里不在说明https://www.cnblogs.com/jssj/p/13472394.html

线程:

主库下执行以下命令,查询线程:

show processlist;

图中可以看到两个 Binlog Dump的主从线程。

从库线程:搭建的第八步已经给出。两个线程一个I/O,一个SQL。

主从复制的原理图:

额外补充: 主库有变化会通过从库,从库就会及时去主库获取新的变化,MySQL的主从复制是通过这种方式来保证实时性的。

参数

mysql> show slave hosts;     -- 查看主库中被连接的从库信息

mysql> show slave status \G;    --查看从库信息

重点字段说明

change master to 的配置信息

Master_Host: 127.0.0.1                             
Master_User: repl                                      
Master_Port: 3307                                     
Connect_Retry: 10                                    
Master_Log_File: mysql-bin.000004         
Read_Master_Log_Pos: 154

Relay_Log_File的执行情况:

Relay_Log_File: iZm5e5v2zi93osbr5z21fvZ-relay-bin.000005      
Relay_Log_Pos: 367                                                                      
Relay_Master_Log_File: mysql-bin.000004

Exec_Master_Log_Pos: 154

从库线程状态:
Slave_IO_Running: Yes              -- no 或者 connecting 都表示不正常。  网络,端口,防火墙,用户密码 ,权限replication slave,连接数上限,版本不一致等。
Slave_SQL_Running: Yes

mysql> select @@max_connections;      -- 最大连接数

从库线程报错信息:

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                          -- 通过主从配置的时候设置的 MASTER_DELAY;

SQL_Remaining_Delay: NULL

GTID相关复制信息:从库显示的就是主库的GTID 和从库执行到的GTID。

Retrieved_Gtid_Set:
Executed_Gtid_Set:

故障

主从不一致的时候,会出现从库SQL线程down掉。

先看参数: 报错内容

Last_SQL_Errno: 0
Last_SQL_Error:

处理方式一:

stop slave;                 --  停主从
set global sql_slave_skip_counter = 1; -- 设置参数跳过本次主从同步操作。
start slave;

处理方式二:

从库反操作一下:比如从库中已经存在主键记录,先把主键记录删除,重启start slave; 让其再同步一次。

处理方式三(统一处理一下重复报错,不推荐):

在MySQL参数配置文件:/etc/my.cnf 中设置

slave-skip-errors = 1032,1062,1007      -- 常见错误代码:1007:对象已存在;1032:无法执行DML;1062:主键冲突,或约束冲突

终极方式:重新搭建主从。

一般情况:MySQL主从搭建从库是不需要有其他的操作的,也是为了减少不必要的主从问题,所以会设置一个参数:

mysql> select @@read_only;     -- 1:只读,0:不是 (针对普通用户)

mysql> select @@super_read_only;   -- 1:只读,0:不是 (针对普通管理员用户)

主从延时

主从延时监控:

主库binlog执行到的位置点:

从库relaylog执行到的位置点,

是否存在差异,差异越大延时越严重。

主从延时原因:

1. 网络太慢。

2. 硬件性能。

3. 主库业务繁忙。

4. 从库太多。

5. 5.6版本没有开启GTID(串行传输日志)。  -- 开启GTID,或者升级5.7 ,5.7默认支持并发传输日志。

6. 锁也会导致延时。

7.从库SQL线程串行执行,效率低,导致延时, 需要开启多个SQL线程来保证效率(必须开启GTID).并且5.7 版本还有逻辑时钟保证并发执行。 MTS

恢复

1. 如果是物理损坏, 主从非常简单的就可以恢复数据。 直接将从库数据导出,导入主库, 或者直接将从库当成主库使用。

stop slave;      -- 停掉主从服务
reset slave all; -- 去掉主从配置

然后就可以临时当主库使用。

2. 如果数逻辑损坏,比如drop了数据库。

上面的情况下,我们就需要使用延时从库的功能了, 因为该从库是延时执行操作的, 故主库出现问题的时候从库是正常的。  所以可以通过从库恢复数据:

CHANGE MASTER TO MASTER_DELAY = 300;   -- 设置延时

1. 登录从库数据库停从库sql线程:

stop slave sql_thread

2. 查看relay.info 的位置点是否主库一致,表示日志文件已经同步:

3. 恢复从库:

截取relay_bin log位置点的起点

show slave status \G;

截取relay_bin log位置点的终点

找到使用的relay-bin 文件,然后使用下面的命令找到终点

show relaylog events in 'iZm5e5v2zi93osbr5z21fvZ-relay-bin.000002'    -- 查看relaybinlog 文件

获取pos字段就可以了,

起点,终点都有了,然后截取命令:

mysqlbinlog --start-position=634 --stop-position=861  /usr/local/mysql/data/3309/data/iZm5e5v2zi93osbr5z21fvZ-relay-bin.000002 > /usr/local/mysql/relay.sql

恢复从库数据:

mysql> set sql_log_bin = 0;    -- 关闭binlog日志
mysql> source /usr/local/mysql/relay.sql; -- 导入sql脚本(通过binlog截取出来的)
mysql> set sql_log_bin = 1; -- 开启binlog日志

检查数据:

4. 恢复主库:

参考:https://www.cnblogs.com/jssj/p/13514597.html  的恢复章节。 导出从库数据库文件,导入主库。

5. 恢复主从:

从新设置主从:参考本文第一部分。

过滤主从

图中 数据库C 不需要主从复制。

1. 主库设置不同步,不产生binlog 即可(不推荐)

其中:binlog_Do_DB  是包含哪些库需要生成binlog日志;      binlog_ignore_DB 忽略掉一些数据库产品binlog日志

2. 从库设置SQL线程不执行不需要复制的数据库(推荐)。

[root@db01 ~]# vim my.cnf           -- 打开参数文件设置
replicate_do_db=test -- 需要写入从库的数据库
replicate_do_db=test1 -- 需要写入从库的数据库

重启数据库实例生效。

扩展:

replicate_do_db=test                -- 需要写入从库的数据库
replicate_ignore_db=test1 -- 需要忽略写入从库的数据库 replicate_do_table=test.test -- 需要写入从库的数据库的表
replicate_ignore_db=test1.test -- 需要忽略写入从库的数据库的表 replicate_wild_do_db=test.t* -- 需要写入从库的数据库的模糊的表
replicate_wild_ignore_db=test1.t* -- 需要忽略写入从库的数据库模糊的表

半同步主从

在上面的主从复制的框架中有一个问题,就是主库不关心从库是否接收到数据,写入磁盘,容易出现从库和主库不一致的情况。

已经属于历史功能,基本已经不使用了。

原理:

1. 主库执行新的事务,commit时,更新 show master status\G ,触发一个信号给
2. binlog dump 接收到主库的 show master status\G信息,通知从库日志更新了
3. 从库IO线程请求新的二进制日志事件
4. 主库会通过dump线程传送新的日志事件,给从库IO线程
5. 从库IO线程接收到binlog日志,当日志写入到磁盘上的relaylog文件时,给主库ACK_receiver线程
6. ACK_receiver线程触发一个事件,告诉主库commit可以成功了
7. 如果ACK达到了我们预设值的超时时间,半同步复制会切换为原始的异步复制.

INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';  -- 主库加载插件
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so'; --从库加载插件
show plugins;       -- 查看加载情况
SET GLOBAL rpl_semi_sync_master_enabled = 1;   -- 主库设置半同步
SET GLOBAL rpl_semi_sync_slave_enabled = 1; -- 从库设置半同步
STOP SLAVE IO_THREAD;     -- 停止I/O线程
START SLAVE IO_THREAD; -- 启动I/O线程
show status like 'Rpl_semi_sync_master_status';    -- 主库查看半同步状态
show status like 'Rpl_semi_sync_slave_status'; -- 从库查看半同步状态

GTID 主从复制(推荐)

搭建GTID主从要注意一点:MySQL的data文件需要清理之后,从新搭建。

my.cnf的配置文件如下:

cat > /usr/local/mysql/data/3307/my.cnf <<EOF
[mysqld]
basedir=/usr/local/mysql/mysql-5.7.22-linux-glibc2.12-x86_64
datadir=/usr/local/mysql/data/3307data
socket=/usr/local/mysql/data/3307/mysql.sock
log_error=/usr/local/mysql/data/3307/mysql.log
port=3307
server_id=7
log_bin=/usr/local/mysql/log/3307/mysql-bin
secure-file-priv=/tmp
binlog_format=row
autocommit=0
gtid-mode=on #开启GTID
enforce-gtid-consistency=true #开启GTID
log-slave-updates=1 #主从一至
[mysql]
prompt=db01 [\\d]>
EOF

重新初始化数据:

mysqld --initialize-insecure --user=mysql --basedir=/usr/local/mysql/mysql-5.7.22-linux-glibc2.12-x86_64  --datadir=/usr/local/mysql/data/3307/data

启动实例:

mysqld --defaults-file=/usr/local/mysql/data/3309/my.cnf &

重新构建主从:主库

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

从库执行命令(和普通主从有区别):

-- 主从配置信息
change master to
master_host='127.0.0.1',
MASTER_PORT=3307,
master_user='repl',
master_password='repl' ,
MASTER_AUTO_POSITION=1; -- 主动获取主库的的位置点,根据从库的relay-bin.info去判断
-- 开启主从
start slave;

原理:

GTID 备份数据,然后复制到从库,从库启动后会自动判断到那些GTID被执行过,可以自动获取下一个GTID. 需要结合--set-gtid-purged。 默认自动开启。

总结

数据安全非常重要,所以数据库保证数据的安全是必须要实现的,这也是为什么会出现主从复制的原因,备份恢复操作比较麻烦,而且物理损坏修复也比较麻烦。主从演变到现在已经比较靠谱和完善了。

《MySQL数据库》MySQL主从复制搭建与原理的更多相关文章

  1. mysql 5.7 主从复制搭建及原理

    1. 主从复制搭建 1.1 环境准备 OS: Ubuntu 18.04 master: 192.168.0.3 slave: 192.168.0.6 1.2 安装依赖包 # Ubuntu apt-ge ...

  2. 一、初识MySQL数据库 二、搭建MySQL数据库(重点) 三、使用MySQL数据库 四、认识MySQL数据库的数据类型 五、操作MySQL数据库的数据(重点)

    一.初识MySQL数据库 ###<1>数据库概述     1. 数据库         长期存储在计算机内的,由组织的可共享的数据集合         存储数据的仓库         文件 ...

  3. windows系统下使用mycat实现mysql数据库的主从复制,从而实现负载均衡

    在之前有记录过在一台系统中安装多台数据库,同时实现主从复制,但是那个主从复制只是一个基于dosc命令的,再实际的开发中我们不会去直接连接数据库,一般情况下我们也是通过间接的采用一些中间件去连接,本来是 ...

  4. 第二百八十四节,MySQL数据库-MySQL触发器

    MySQL数据库-MySQL触发器 对某个表进行[增/删/改]操作的前后如果希望触发某个特定的行为时,可以使用触发器,触发器用于定制用户对表的行进行[增/删/改]前后的行为. 1.创建触发器基本语法 ...

  5. 第二百八十六节,MySQL数据库-MySQL事务操作(回滚)

    MySQL数据库-MySQL事务操作(回滚) 事务用于将某些操作的多个SQL作为原子性操作,一旦有某一个出现错误,即可回滚到原来的状态,从而保证数据库数据完整性. 举例:有这样一张表 从表里可以看出张 ...

  6. 第二百八十五节,MySQL数据库-MySQL函数

    MySQL数据库-MySQL函数 1.MySQL内置函数 SELECT执行函数,后面跟要执行的函数 CHAR_LENGTH(str)函数:返回字符串的字符长度 -- CHAR_LENGTH(str)函 ...

  7. 第二百八十三节,MySQL数据库-MySQL存储过程

    MySQL数据库-MySQL存储过程 MySQL存储过程,也就是有点像MySQL函数,但是他与MySQL函数是有区别的,后面会讲到函数,所以注意区分 注意:函数与存储过程的区别 存储过程是:CREAT ...

  8. 第二百八十二节,MySQL数据库-MySQL视图

    MySQL数据库-MySQL视图 1.视图是一个虚拟表(非真实存在),其本质是[根据SQL语句获取动态的数据集,并为其命名],用户使用时只需使用[名称]即可获取结果集,并可以将其当作表来使用. 2.也 ...

  9. MySQL数据库”mysql SQL Error:1146,SQLState:42S02 “解决方法

    项目在开发的时候在Mac平台下开发的,开发完了之后在LINUX环境上部署好之后,运行时MySQL数据库报错,提示为某个表不存在之类的错误信息,后来修改了MySQL的配置文件将大小写敏感去掉,问题解决. ...

  10. 【Data Cluster】真机环境下MySQL数据库集群搭建

    真机环境下MySQL-Cluster搭建文档  摘要:本年伊始阶段,由于实验室对不同数据库性能测试需求,才出现MySQL集群搭建.购置主机,交换机,双绞线等一系列准备工作就绪,也就开始集群搭建.起初笔 ...

随机推荐

  1. ZROI 提高十连测 Day1

    第一天的提高模拟测 考前特意睡了20min 还是歇菜了,果然自己菜是真实的. 题目质量海星 但是我都不会这是真的...题目由于是花钱买的这里就不放了 LINK:problem 熟悉我的人应该都知道账号 ...

  2. navicat for mysql 连接报错1251的解决方法

    这是因为比较新的mysql版本采用新的保密方式,若要用navicat连接需要改使用到的用户的密码方式:use mysql:ALTER USER 'root'@'localhost' IDENTIFIE ...

  3. Linux的VMWare下Centos7的三种网络配置过程(网络二)

    Linux之VMWare下Centos7的三种网络配置过程 环境:虚拟软件:VMWare 14.0客户机:windows 10虚拟机:centos 7 VMware三种网络连接方式 Bridge(桥接 ...

  4. 028_go语言中的超时处理

    代码演示 package main import "fmt" import "time" func main() { c1 := make(chan strin ...

  5. 解决使用rollup构建ECharts过程中遇到的问题

    1.ECharts官方文档 参考:自定义构建 ECharts - ECharts Documentation 2.解决问题 改动一: // line.js // 引入 echarts 主模块. // ...

  6. IOS - ACL (访问控制列表)

    ACL 介绍 ACL 是一款 IOS 软件工具,而不是某种协议.从名字上来看,ACL 的主要功能是控制对网络资源的访问.事实上这是 ACL 最早的用途.现在 ACL 除了能够限制访问外,更多时候,我们 ...

  7. Python中 *args 和 **kwargs 的含义?

    答:在python中,*args和**kwargs通常使用在函数定义里.*args 和 **kwargs 都允许你给函数传不定数量的参数,即使在定义函数的时候不知道调用者会传递几个参数.ps: *ar ...

  8. Java—接口

    接口概念 接口是功能的集合,同样可看做是一种数据类型,是比抽象类更为抽象的”类”. 接口只描述所应该具备的方法,并没有具体实现,具体的实现由接口的实现类(相当于接口的子类)来完成.这样将功能的定义与实 ...

  9. 《闲扯Redis十》Redis 跳跃表的结构实现

    一.前言 Redis 提供了5种数据类型:String(字符串).Hash(哈希).List(列表).Set(集合).Zset(有序集合),理解每种数据类型的特点对于redis的开发和运维非常重要. ...

  10. 02树莓派4B—C语言编程——PWM

    01树莓派直接输出PWM波 —— 硬件PWM程序  (推荐使用) #include <stdio.h> #include <wiringPi.h> #include <s ...