当前位置: 首页 > news >正文

MySQL主从复制详解

文章目录

    • 1. 简介
      • 1.1 应用场景
      • 1.2 复制形式
    • 2. 复制原理
    • 3. 复制类型
      • 3.1 异步复制
      • 3.2 同步复制
      • 3.3 半同步复制
    • 4. 复制方式
      • 4.1 语句复制(Statement格式)
      • 4.2 行数据复制(Row格式)
      • 4.3 混合类型复制(Mixed格式)
    • 5. 一主一从配置
      • 5.1 主机修改my.cnf配置文件
      • 5.2 主库创建用于主从复制的账号
      • 5.3 从机修改my.cnf配置文件
      • 5.4 启动从服务器复制功能
      • 5.5 停止主从复制
    • 6. 主从延迟问题
      • 6.1 延迟问题
      • 6.2 数据丢失问题

1. 简介

随着业务流量的增长,一台MySQL数据库服务器已经满足不了需求了,会负载过重,容易出现宕机的情况,导致数据的丢失。这个时候就需要实现数据库的负载均衡和读写分离,来减少单台MySQL数据库服务器的压力。我们可以通过使用MySQL内置的复制功能来搭建MySQL一主一从或一主多从的集群环境。主服务器只负责写,而从服务器只负责读,从而减少单台MySQL数据库服务器的压力。

MySQL的复制功能不仅有利于构建高性能的应用,同时也是高可用性、可扩展性、灾难恢复、备份以及数据仓库等工作的基础。

1.1 应用场景

MySQL 主从复制集群功能使得 MySQL 数据库支持大规模高并发读写成为可能,同时有效地保证了物理服务器宕机场景的数据备份。MySQL主从复制比较常见的应用场景如下:

  • 横向拓展

将工作负载分发到各 Slave 节点上,从而提高系统性能。

在这个场景下,所有的写和更新操作都在 Master 节点上完成;所有的读操作都在 Slave 节点上完成。通过增加更多的 Slave 节点,便能提高系统的读取速度。

  • 数据安全

数据从 Master 节点复制到 Slave 节点上,在 Slave 节点上可以暂停复制进程。可以在 Slave 节点上备份与 Master 节点对应的数据,而不用影响 Master 节点的运行。

  • 数据分析

实时数据可以在 Master 节点上创建,而分析这些数据可以在 Slave 节点上进行,并且不会对 Master 节点的性能产生影响。

  • 远距离数据分布

可以利用复制在远程主机上创建一份本地数据的副本,而不用持久的与Master节点连接。

  • 拆分访问

可以把几个不同的从服务器,根据公司的业务进行拆分。通过拆分可以帮助减轻主服务器的压力,还可以使数据库对外部用户浏览、内部用户业务处理及 DBA 人员的备份等互不影响。

1.2 复制形式

MySQL主从复制的基本原则是:

  1. 每个slave只有对应一个master
  2. 每个slave只能有一个唯一的服务器ID
  3. 每个master可以有多个salve

基于上述的基本原则,MySQL主从复制的形式包括有:

  • 一主一从

  • 一主多从

  • 多主一从:多主一从可以将多个 MySQL 数据库备份到一台存储性能比较好的服务器上。

  • 双主复制:双主复制,也就是可以互做主从复制,每个 master 既是 master,又是另外一台服务器的 salve。这样任何一方所做的变更,都会通过复制应用到另外一方的数据库中。

  • 级联复制:级联复制模式下,部分 slave 的数据同步不连接主节点,而是连接从节点。
    因为如果主节点有太多的从节点,就会损耗一部分性能用于 replication ,那么我们可以让 3~5 个从节点连接主节点,其它从节点作为二级或者三级与从节点连接,这样不仅可以缓解主节点的压力,并且对数据一致性没有负面影响。

2. 复制原理

主从复制的工作原理就是slave从库会从master主库读取binlog来进行数据同步。
在这里插入图片描述
上图说明,MySQL主从复制过程分成四步:

  1. 从库生成两个线程,一个 I/O 线程一个 SQL 线程
  2. 当从库连接主库时,主库会生成一个 二进制转储(binlog dump) 线程,用来给从库 I/O 线程传 binlog
  3. I/O 线程去请求主库的 binlog,并将得到的 binlog 日志写到 relay log(中继日志) 文件中。(在读取 binlog 的内容的操作中,会对主库的 binlog 加锁,当binlog读取完成并发送给从库后解锁。)
  4. 从SQL 线程会读取 relay log 文件中的日志,并解析成具体操作,来实现主从的操作一致,最终实现主从的数据一致。

复制过程有一个很重要的限制,就是复制在从库上是串行化的,也就是说主库上的并行更新操作不能在 从库上并行操作。

3. 复制类型

3.1 异步复制

异步复制指主库以异步的方式同步数据到一个从库或多个从库中。

在这里插入图片描述
这种模式下,主节点不会主动推送数据到从节点,主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已经接收并处理。

这样就会有一个问题,主节点如果崩溃掉了,此时主节点上已经提交的事务可能并没有传到从节点上,如果此时,强行将从节点提升为主节点,可能导致新主节点上的数据不完整。

3.2 同步复制

同步复制是在MySQL cluster 中特有的复制方式。

当主库执行完一个事务,然后所有的从库都复制了该事务并成功执行完才返回成功信息给客户端。

因为需要等待所有从库执行完该事务才能返回成功信息,所以全同步复制的性能必然会收到严重的影响。

3.3 半同步复制

在异步复制的基础上,确保任何一个主库上的事务在提交之前至少有一个从库已经收到该事务并记录下日志。
在这里插入图片描述

介于异步复制和全同步复制之间,主库在执行完客户端提交的事务后不是立刻返回给客户端,而是等待至少一个从库接收到并写到 relay log 中才返回成功信息给客户端(只能保证主库的 Binlog 至少传输到了一个从节点上),否则需要等待直到超时时间然后切换成异步模式再提交。

相对于异步复制,半同步复制提高了数据的安全性,一定程度的保证了数据能成功备份到从库,同时它也造成了一定程度的延迟,但是比全同步模式延迟要低,这个延迟最少是一个 TCP/IP 往返的时间。所以半同步复制最好在低延时的网络中使用。

半同步模式不是 MySQL 内置的,从 MySQL 5.5 开始集成,需要 master 和 slave 安装插件开启半同步模式。

另外还有一个延迟复制的模式,延迟复制是在异步复制的基础上,人为设定主库和从库的数据同步延迟时间。

4. 复制方式

下面介绍的三种复制方式对应者binlog的三种格式:

  • Statement(Statement-Based Replication,SBR):每一条会修改数据的 SQL 都会记录在 binlog 中。
  • Row(Row-Based Replication,RBR):不记录 SQL 语句上下文信息,仅保存哪条记录被修改。
  • Mixed(Mixed-Based Replication,MBR):Statement 和 Row 的混合体。

4.1 语句复制(Statement格式)

MySQL 默认采用基于语句的复制,基于语句的复制相当于逻辑复制,即二进制日志binlog 中记录了操作的语句,通过这些语句在从数据库中重放来实现复制。语句复制只记录执行的 会修改数据的SQL,不需要记录每一行数据的变化,因此极大的减少了 binlog 的日志量,避免了大量的 IO 操作,提升了系统的性能。

但是基于语句更新依赖于其它因素,比如插入数据时利用了时间戳或者uuid。每次执行的结果都不一样,那么就可能会出现在主服务器和从服务器中执行结果不一致的情况。因此在开发当中,我们应该尽量将业务逻辑逻辑放在代码层,而不应该放在 MySQL 中

语句复制的特点:

  • 传输效率高,减少延迟。
  • 在从库更新不存在的记录时,语句赋值不会失败。而行复制会导致失败,从而更早发现主从之间的不一致。
  • 可能出现数据一致性问题

4.2 行数据复制(Row格式)

基于行的复制相当于物理复制,这种方式会将实际数据记录在二进制日志中。这样会导致复制的压力比较大,特别是批量 update、整表 delete、alter 表等操作,由于要记录每一行数据的变化,此时会产生大量的日志,大量的日志也会带来 IO 性能问题。

大量的binlog日志占用的空间大,传输带宽占用大。但是这种方式比基于语句的复制要更加精确。

4.3 混合类型复制(Mixed格式)

混合类型复制的方式是,一般情况下,默认采用基于语句的复制,对于基于语句复制的方式无法精确完成主从复制时,就会采用基于行的复制。简单来说,混合类型复制方式中,MySQL会根据执行的每一条具体的SQL语句来区别对待记录的日志格式,即语句复制(Statement)和行复制(Row)中选一种。

5. 一主一从配置

首先建议MySQL主机和从机的版本保持一致并且后台以服务运行。下面基于MySQL5.5.48搭建一主一从的MySQL服务配置。

MySQL安装教程:MySQL安装及常用配置与管理命令总结

5.1 主机修改my.cnf配置文件

  1. 【必须】设置主服务器唯一ID
[mysqld]
#配置唯一的服务器ID,一般使用IP最后一位
server-id=7

一种通用的做法是使用服务器IP地址的末8位,但要保证它是不变且唯一的。
2. 【必须】启用二进制日志

[mysqld]
#开启log-bin二进制日志
log-bin=/var/log/mysql/mysql-bin
  1. 【可选】启动错误日志
log-err=/var/log/mysql/mysql-error
  1. 【可选】设置根目录
basedir=
  1. 【可选】临时目录
tmpdir=
  1. 【可选】设置数据目录
datadir=
  1. 【可选】设置不要复制的数据库
[mysqld]
#设置不要复制的数据库
binlog-ignore-db=mysql
  1. 【可选】设置需要复制的数据库
[mysqld]
#设置需要复制的数据库
binlog-do-db=需要复制的主数据库名字

重启数据库,并查看配置是否生效

show variables like 'server_id';

在这里插入图片描述

show variables like 'log_bin';

在这里插入图片描述

#skip_networking默认是OFF关闭状态,启用后主从将无法通信
show variables like '%skip_networking%';

在这里插入图片描述

5.2 主库创建用于主从复制的账号

在主库上创建用于主从复制的账号

CREATE USER 'rep_user'@'%';
GRANT REPLICATION SLAVE ON *.*  TO  'rep_user'@'%'  identified by '123';

在这里插入图片描述
查看主库的二进制日志的名称,File和Position两个参数需要在从库配置中使用。

show master status\G

在这里插入图片描述

5.3 从机修改my.cnf配置文件

首先可以在从机上测试能否连接主机服务器

 mysql -u rep_user -123' -h 192.168.169.7

确认可以成功连接后再进行下面的操作

  1. 【必须】设置主服务器唯一ID
#配置唯一的服务器ID,一般使用IP最后一位
server-id=132
  1. 【必须】开启中继日志,从主服务器上同步日志文件记录到本地
relay-log=relay-log-bin
  1. 【必须】定义中继日志文件的位置和名称
relay-log-index=slave-relay-bin.index

保存my.cnf配置文件并重启服务器。此外主机和从机都需要关闭防火墙。如果是windows系统则需要手动关闭,如果是Linux系统则使用service iptables stop命令关闭或者配置防火墙的开放规则。

5.4 启动从服务器复制功能

在从服务器中配置复制参数

CHANGE MASTER TO MASTER_HOST='192.168.169.7',MASTER_USER='rep_user',MASTER_PASSWORD='123',MASTER_LOG_FILE='mysql-bin.000002',MASTER_LOG_POS=338;

查看slave的状态

 show slave status\G

在这里插入图片描述
其中重点关注这两个参数,需要确保这两个参数的值都为Yes,主从配置才算成功:

  • Slave_IO_Running:IO线程,负责与主机的io通信
  • Slave_SQL_Running:SQL线程,责自己的slave MySQL进程

5.5 停止主从复制

如果需要停止主从服务复制的功能,使用以下命令:

stop slave;

若搭建主从复制的过程出错,则需要清理掉之前的配置,还需要执行以下命令:

reset slave all;

6. 主从延迟问题

6.1 延迟问题

当主库的 TPS 并发较高的时候,由于主库上面是多线程写入的,而从库的SQL线程是单线程的,导致从库SQL可能会跟不上主库的处理速度。

解决方法:

  • 网络方面:尽量保证主库和从库之间的网络稳定,延迟较小;
  • 硬件方面:从库配置更好的硬件,提升随机写的性能;
  • 配置方面:尽量使 MySQL 的操作在内存中完成,减少磁盘操作。或升级 MySQL5.7 版本使用并行复制;
  • 建构方面:在事务中尽量对主库读写,其它非事务的读在从库。消除一部分延迟带来的数据库不一致。还可以增加缓存降低一些从库的负载。

6.2 数据丢失问题

当主库宕机后,数据可能丢失。使用半同步复制,可以解决数据丢失的问题。

参考:
1.《高性能MySQL》第3版
2.MySQL主从复制那些破事,你不好奇吗

相关文章:

  • 【深度学习入门】- 用电路思想解释感知机
  • 文字生成图片
  • HTTPS的原理浅析与本地开发实践(下)
  • java-多态
  • 一、CSS文本样式[文本基础、文本样式、段落控制]
  • Nginx网络服务的配置
  • m基于随机接入代价的异构网络速率分配算法matlab仿真(包括matlab仿真录像)
  • 【VUE的Form表单】使用v-if切换控件时,表单校验不生效
  • EnumWindowsProc
  • SSL安全证书:免费的SSL证书申请渠道有哪些?
  • SQL语言---数据的查询
  • 建模杂谈系列162 APIFunc: 可靠的复杂函数开发3
  • nslookup命令的常见用法
  • 如果你也想在linux中删除指定行
  • 掩码和反掩码的使用场景
  • 【Amaple教程】5. 插件
  • 【译】React性能工程(下) -- 深入研究React性能调试
  • CentOS从零开始部署Nodejs项目
  • conda常用的命令
  • gf框架之分页模块(五) - 自定义分页
  • input实现文字超出省略号功能
  • iOS 系统授权开发
  • Laravel 中的一个后期静态绑定
  • MySQL几个简单SQL的优化
  • SpiderData 2019年2月13日 DApp数据排行榜
  • Spring Boot快速入门(一):Hello Spring Boot
  • 第13期 DApp 榜单 :来,吃我这波安利
  • 回顾2016
  • 什么是Javascript函数节流?
  • 算法---两个栈实现一个队列
  • 完善智慧办公建设,小熊U租获京东数千万元A+轮融资 ...
  • ​插件化DPI在商用WIFI中的价值
  • #传输# #传输数据判断#
  • $.extend({},旧的,新的);合并对象,后面的覆盖前面的
  • (2)MFC+openGL单文档框架glFrame
  • (4)Elastix图像配准:3D图像
  • (function(){})()的分步解析
  • (rabbitmq的高级特性)消息可靠性
  • (篇九)MySQL常用内置函数
  • (三)终结任务
  • (十三)Maven插件解析运行机制
  • (转) Android中ViewStub组件使用
  • 、写入Shellcode到注册表上线
  • .NET 中什么样的类是可使用 await 异步等待的?
  • .NET/C# 解压 Zip 文件时出现异常:System.IO.InvalidDataException: 找不到中央目录结尾记录。
  • .NET单元测试
  • .NET构架之我见
  • .NET开源项目介绍及资源推荐:数据持久层
  • .net连接oracle数据库
  • .net生成的类,跨工程调用显示注释
  • [.NET 即时通信SignalR] 认识SignalR (一)
  • [20171113]修改表结构删除列相关问题4.txt
  • [3D基础]理解计算机3D图形学中的坐标系变换
  • [Angular] 笔记 18:Angular Router
  • [BZOJ 4034][HAOI2015]T2 [树链剖分]