10、复制

复制概述

复制解决的基本问题是让一台服务器的数据与其他服务器保持同步。一台主库的数据可以同步到多台备库上,备库本身也可以被配置成另外一台服务器的主库。主库和备库之间可以有多种不同的组合方式。
Mysql 支持两种复制方式:基于行的复制和基于语句的复制。这两种方式都是通过在主库上记录二进制日志,在备库重放日志的方式来实现异步的数据复制的。这意味着,在同一时间点备库上的数据可能与主库存在不一致,并且无法保证主备之间的延迟。一些大的语句可能导致备库产生几秒,几分钟甚至几个小时的延迟。
复制通常不会增加主库的开销,主要是启用二进制日志带来的开销。每个备库也会对主库增加一些负载,尤其当备库请求从主库读取旧的二进制日志文件时,可能会造成更高的IO开销。另外锁竞争也可能阻碍事务的提交。

复制解决的问题

数据分布

Mysql 复制通常不会对带宽造成很大的压力。

负载均衡

通过 Mysql 复制可以将读操作分布到多个服务器上,实现对读密集型应用的优化,并且实现方便。

备份

对于备份来说,复制是一项很有意义的技术补充,但是复制不是备份也不能取代备份。

高可用性和故障切换

复制能够帮助应用程序避免Mysql单点失败,一个包含复制的故障切换系统能够缩短宕机时间。

复制如何工作

复制有三个步骤:

  1. 在主库上把数据更改记录到二进制日志中。
  2. 备库将主库上的日志复制到自己的中继日志中。
  3. 备库读取中继日志中的事件,将其重放到备库数据之上。

第一步是在主库上记录二进制日志。在每次提交事务完成数据之前,主库将数据更新的事件记录到二进制日志中。Mysql会按事务提交的顺序而非每条语句的执行顺序来记录二进制日志。在记录二进制日志后,主库会告诉存储引擎可以提交事务了。
第二步备库将主库的二进制日志复制到本地的中继日志中。首先备库会启动一个工作线程即IO线程,IO线程跟主库建立一个普通的客户端连接,然后再主库上启动一个特殊的dump线程,这个 dump 线程会读取主库上二进制日志中的事件。如果该线程追上了主库,就会进入休眠状态,直到主库发送信号量通知 dump 线程有新的事件产生。备库IO线程会将接收到的事件记录到中继日志中。
第三步备库会开启一个SQL线程,该线程从中继日志中读取事件并在备库执行,从而实现备库数据的更新。当SQL线程追赶上IO线程时,中继日志通常已经在系统缓存中,所以中继日志的开销很低。
Mysql 的这种主备复制架构实现了获取事件和重放事件的解耦,允许两个过程异步运行。

配置复制

总的分为以下几步:

  1. 在每台服务器上创建复制账号2. 配置主库和备库3. 通知备库连接到主库并从主库复制数据

创建复制账号

Mysql 会赋予一些特殊的权限给复制线程。在备库运行的IO线程会建立一个到主库的TCP/IP连接。

配置主库和备库

假设主库是服务器 server1,需要打开二进制日志并制定一个唯一的服务器ID,在主库的 my.cnf 文件中增加以下配置

log_bin=mysql-bin
server_id=1

备库也要在 my.cnf 文件中增加相应的配置,并且都需要重启服务器

log_bin=mysql-bin
server_id=2
relay_log=/var/lib/mysql/mysql-relay-bin
log_slave_updates=1
read_only=1

启动复制

这一步需要告诉备库如何连接到主库并重放二进制日志,我们可以使用 CHANGE MASTER TO 语句替代 my.cnf 中的配置,并且以后需要指向别的主库时无须重启备库。

CHANGE MASTER TO MASTER_HOST='SERVER1',
MASTER_USER='USER1',
MASTER_PASSWORD='PWD1',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=0; # 指定日志开始读取的位置,初始值为0,从头开始读

从另一个服务器开始复制

大多数情况下,我们是从一台已经运行一段时间的主库复制数据到新的备库。目前有几种方法来初始化备库或者从其他服务器克隆数据到备库。包括从主库复制数据、从另外一台备库克隆数据、以及使用最近的一次备份来启动备库,需要三个条件来让主库和备库保持同步:

  1. 某个时间点的主库的数据快照
  2. 主库当前的二进制日志文件,或获得数据快照时在该二进制日志文件中的偏移量
  3. 从快照时间到现在的二进制日志

推荐的复制配置

在主库上二进制日志最重要的选项是 sync_binlog:

sync_binlog=1

如果该选项开启,Mysql每次提交事务前会将二进制日志同步到磁盘上,保证在服务器崩溃时不会丢失事件。如果禁止该选项,服务器会少做一些工作,但二进制日志文件可能在服务器崩溃时损坏或丢失信息。在备库上该选项会带来不必要的开销,所以他只适用于二进制日志。

复制的原理

基于语句的复制

Mysql 5.0及以前的版本中只支持基于语句的复制。在基于语句的复制模式下,主库会记录那些造成数据更改的查询。当备库读取并重放这些事件时,实际上只是把主库上执行过的SQL再执行一遍。
这种方式最明显的好处就是实现简单。理论上讲,简单地记录和执行这些语句,能够让主备保持同步,另一个好处就是二进制日志里的事件更加紧凑。当然这种方式的缺点就是更新必须串行,需要更多的锁。

基于行的复制

Mysql 5.1开始支持基于行的复制,这种方式会将实际数据记录到二进制日志中,最大的好处就是可以正确地复制每一行。

基于行或基于语句哪个更优

基于语句的复制模式的优点

当主备的模式不同时,逻辑复制能够在多种情况下工作。例如在主备上的表的定义不同,但数据类型相兼容、列的顺序不同等情况。这样就很容易先在备库上修改schema,然后将其提升为主库,减少停机时间。
基于语句的方式执行复制的过程基本上就是执行SQL语句,这意味着所有在服务器上发生的变更都以一种容易理解得方式运行。

基于语句的复制模式的缺点

很多情况下通过基于语句的复制无法正确复制。事实上对于存储过程,触发器以及其他的一些复制语句在5.0和5.1版本中存在大量bug。

基于行的复制模式的优点

几乎没有基于行的复制模式无法处理的场景,对于所有的SQL构造、触发器、存储过程等都能正确执行。这种方式同样能减少锁的使用,因为并不要求串行化执行。

基于行的复制模式的缺点

由于语句并没有在日志里记录,因此无法判断执行了哪些SQL。

复制拓扑

可以在任意个主库和备库之间建立复制,但是有一个限制:每一个备库只能有一个主库。
基本原则是:

  1. 一个Mysql 备库实例只能有一个主库2. 每个备库必须有一个唯一的服务器ID3. 一个主库可以有多个备库4. 如果打开了 log_slave_updates 选项,一个备库可以把其主库上的数据变化传播到其他备库

一主库多备库

有以下一些用途:

  1. 为不同的角色使用不同的备库
  2. 把一台备库当做待用的主库,除了复制没有其他数据传输
  3. 将一台备库放到远程数据中心,用作灾难恢复
  4. 延迟一个或多个备库,以备灾难恢复
  5. 使用其中一个备库,作为备份、培训、开发或测试使用服务器

主动-主动模式下的主-主复制

主-主复制包含两台服务器,每一台都被配置成对方的主库和备库。其实就是一对主库。但是这样配置的话,两个可写的主库容易导致写冲突。

主动-被动模式下的主-主复制

便于切换主动和被动服务器,很容易进行故障转移和故障恢复。

拥有备库的主-主结构

这种配置的优点是增加了冗余,对于不同地理位置的复制拓扑,能够消除站点单点失效的问题。

主库、分发主库以及备库

如果需要多个备库,一个比较好的方法就是从主库移除负载并使用分发主库。分发主库事实上也是一个备库,他的唯一目的就是提取和提供主库的二进制日志。

树或金字塔形

这种设计的好处是减轻了主库的负担。缺点是中间层出现的任何错误都会影响到多个服务器。如果每个备库和主库直接相连就不会存在这样的问题。

定制的复制方案

  1. 选择性复制
  2. 分离功能
  3. 数据归档
  4. 将备库用作全文索引
  5. 只读备库
  6. 模拟多主库复制
  7. 创建日志服务器

复制的问题和解决方案

数据损坏或丢失的错误

由于各种原因,Mysql 的复制并不能很好的从服务器崩溃、断电、磁盘损坏、内存或网络错误中恢复。大部分由于非正常关机后导致的复制问题都是由于没有把数据及时的刷到磁盘。下面是意外关闭服务器的几种情况:

  1. 主库意外关闭

如果没有设置主库的 sync_binlog 选项,就可能在崩溃前没有将最后的几个二进制日志事件刷新到磁盘中。备库UI线程因此也可能一直处于读不到尚未写入磁盘的事件。当主库重新启动时,备库将重新连到主库并再次尝试读取该事件,但是主库会告诉备库没有这个二进制日志的偏移量。
解决这个问题的方法是指定备库从下一个二进制日志的开头读取。但是一些日志事件会永久丢失。可以通过在主库开启 sync_binlog 来避免事件丢失。即使开启了 sync_binlog,MyISAM表的数据仍然可能在崩溃的时候损坏,对于InnoDB表,如果innodb_flush_log_at_trx_commit 没有设为1,也可能丢失数据。

  1. 备库意外关闭

当备库意外关闭后重启时,回去读 master.info 文件找到上次停止复制的位置。但是该文件并没有同步写到磁盘。如果使用的都是InnoDB表,可以在重启后观察Mysql的错误日志。InnoDB在恢复过程中会打印出他的恢复点的二进制日志坐标。

除了由于Mysql 意外关闭导致的数据丢失外,也有很多场景导致磁盘上的二进制日志或中继日志文件损坏:

  1. 主库上的二进制日志损坏

如果主库上的二进制日志损坏,除了忽略损坏的位置外别无选择。可以在主库上执行 FLUSH LOGS 命令,这样主库会开始一个新的日志文件。

  1. 备库上的中继日志损坏

如果主库上的日志是完好的,就可以通过 CHANGE MASTER TO 命令丢弃并重新获取损坏的事件,只需要将备库指向他当前正在复制的位置,这会导致备库丢弃所有在磁盘上的中继日志。

  1. 二进制日志与InnoDB事务日志不同步

当主库崩溃时,InnoDB可能将一个事务标记为已提交,此时该事务可能还没有记录到二进制日志中。除非是某个备库的中继日志已经保存,否则没有办法恢复丢失的事务。在Mysql5.0版本可以设置 sync_binlog 来避免该问题。

当一个二进制日志损坏时,能恢复多少数据取决于损坏的类型:

  1. 数据改变,但事件仍是有效的SQL

Mysql无法察觉这种损坏,最好还是经常检查备库的数据是否正确。

  1. 数据改变并且事件也是无效的SQL

可以通过 mysqlbinlog 命令提取出事件并看到一些错误数据。

  1. 数据遗漏并且事件的长度是错误的

这种情况下 mysqlbinlog 可能会发生错误退出或者直接崩溃,因为他无法读取事件,并且找不到下一个事件的开始位置。

  1. 某些事件已经损坏或被覆盖,或者偏移量已经改变并且下一个事件的起始偏移量也是错误的

使用非事务型表

如果一切正常,基于语句的复制能够很好地处理非事务型表,但是当对非事务型表的更新发生错误时,就可能导致主备数据不一致。
如果使用的是MyISAM表,在关闭Mysql之前需要确保已经运行了STOP SLAVE ,否则服务器在关闭时会 kill 所有正在运行的查询。事务型存储引擎则没有这个问题。

混合事务型和非事务型表

如果使用的是事务型存储引擎,只有在事务提交后才会将查询记录到二进制日志中。因此如果事务回滚,Mysql 就不会记录这条查询,也就不会在备库上重放。
但是如果混合适合事务型和非事务型表,并且发生了一次回滚,Mysql 能够回滚事务型表的更新,但非事务型表则被永久地更新了。
防止这个问题的方法就是避免混合使用事务型和非事务型表。

不确定语句

当使用基于语句的复制模式时,如果通过不确定的方式更改数据可能会导致主备不一致。例如使用带 LIMIT 关键字的 UPDATE 操作更改的数据取决于查询找的顺序,除非能保证主备上的顺序相同。
一般禁止对UPDATE 操作使用 LIMIT 关键字。

主库和备库使用不同的存储引擎

当使用基于语句的复制时,如果备库使用了不同的存储引擎,则可能造成一条查询在主库和备库上的执行结果不同。
如果发现主库和备库的某些表已经不同步,除了检查更新这些表的查询外,还要检查两天服务器上使用的存储引擎是否相同。

备库发生数据改变

基于语句的复制前提是确保备库上有和主库相同的数据,因此不应该允许对备库数据的任何更改。如果备库上某个表的数据跟主库不一样,INSERT INTO table1 SELECT * FROM table2;该语句会导致 table1表的数据也不一致。解决的唯一方法就是重新从主库同步数据。

不唯一的服务器ID

如果给两天服务器设置了一样的ID,在主库上会发现只有一台能连接到主句上,在备库的错误日志中,则会发现反复的重连和连接断开的信息。解决的唯一方法是小心设置服务器ID。

未定义的服务器ID

如果没有在 my.cnf 里定义服务器ID,可以通过 CHANGE MASTER TO来设置备库。但是却无法启动复制。必须为备库显示的设置服务器ID。

对未复制数据的依赖性

如果在主库上有备库不存在的数据库或表,服务很容易被中断,唯一的方法就是避免在主库上创建备库上没有的表。

丢失的临时表

临时表在某些时候比较有用,他与基于语句的复制方式是不相容的。如果备库崩溃或者正常关闭,任何复制线程拥有的临时表都会丢失。重启备库后,所有依赖于该临时表的语句都会失败。

不复制所有的更新

如果错误地使用 SET SQL_LOG_BIN=0或者没有理解过滤规则,备库可能会丢失主库上已经发生的更新。

InnoDB加锁读引起的锁争用

正常情况下,InnoDB的读操作是非阻塞的,但在某些情况下需要加锁。特别是在使用基于语句的复制时,执行 INSERT … SELECT 操作会锁定表上的所有行。Mysql需要加锁确保该语句的执行结果在主库和备库上是一致的。实际上,加锁导致主库上的语句串行化,以确保和备库上执行的方式相同。
这种设计会导致锁竞争、阻塞,以及锁等待等超时情况。一种缓解的办法就是避免让事务开启太久以减少阻塞。把大命令拆分成小命令,使其尽可能简短。另一种方式就是替换掉 INSERT … SELECT 语句。

过大的复制延迟

复制延迟是一个很普遍的问题。Mysql单线程复制的设计导致备库的效率相当低下。即使备库有很多磁盘、CPU或这内存。因为备库的单线程通常只会有效的使用一个CPU和磁盘。
复制一般有两种产生延迟的方式:突然产生延迟然后再跟上或者稳定的延迟增大。前者通常是由于一条运行很长时间的查询导致的,而而后者即使没有长时间运行的查询时也会出现。

来自主库的过大的包

受限制的复制带宽

磁盘空间不足

复制的局限性

复制有多快

简单来讲,与Mysql从主库复制事件并在备库重放的速度一样。如果网络很慢并且二进制日志事件很大,记录二进制日志和在备库上执行的延迟可能会非常明显。如果查询需要执行很长时间而网络很快,通常认为查询时间占据了更多的复制时间开销。

Mysql复制的高级特性

第一个是半同步复制,可以帮助确保备库拥有主库数据的拷贝,减少了潜在的数据丢失危险。
半同步复制在提交过程中增加了一个延迟:当提交事务时,在客户端接收到查询结束反馈前必须保证二进制日志已经传输到至少一台备库上,主库将事务提交到磁盘上之后会增加一些延迟。同样的,这也增加了客户端的延迟。因此其执行大量事务的速度不会比将这些事务传递给备库的速度快。
除了半同步复制,Mysql5.5还提供了复制心跳,保证备库一直与主库相联系,避免悄无声息地断开连接。如果出现断开的网络连接,备库会注意到丢失的心跳数据。当使用基于行的复制时,还提供了一种改进的能力来处理主库和备库上不同的数据类型。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/588527.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

向表达式添加括号后的最小结果

说在前面 🎈不知道大家对于算法的学习是一个怎样的心态呢?为了面试还是因为兴趣?不管是出于什么原因,算法学习需要持续保持。 题目描述 给你一个下标从 0 开始的字符串 expression ,格式为 “num1num2” ,…

ArkTS - 组件生命周期

一、先说下自定义组件 在arkTs中,自定义组件分为两种(我的总结): 一种是:根组件,就是被装饰器Entry装饰的入口组件,这也是自定义组件(父组件)。 另一种是:没有被Entry装饰的自定义…

跟我学c++中级篇——再谈C++20中的协程

一、协程 在前面分析过协程是什么,也对c20中的协程的应用进行了举例说明。所以这次重点分析一下c20中的整体构成及应用的方式。等明白了协程是如何动作的,各种情况下如下何处理相关的事件,那么在以后写协程时就不会死搬硬套了。 二、整体说…

分布式存储考点梳理 + 高频面试题

欢迎来到分布式存储模环节,本文我将和你一起梳理面试中分布式系统的数据库的高频考点,做到温故知新。 面试中如何考察分布式存储 广义的分布式存储根据不同的应用领域,划分为以下的类别: 分布式协同系统 分布式文件系统 分布式…

Xline command 去重机制(一)—— RIFL 介绍

为什么要对 command 去重? 在一个接收外部 command 的系统中,通常一个 command 至少要执行一次,我们称其为 at-least-once semantics。如果一个 command 执行失败,系统内部经常会实现一套重试结构来尝试恢复这个问题,…

HTML 基础

文章目录 01-标签语法标签结构 03-HTML骨架04-标签的关系05-注释06-标题标签07-段落标签08-换行和水平线09-文本格式化标签10-图像标签图像属性 11-路径相对路径绝对路径 12-超链接标签13-音频14-视频 01-标签语法 HTML 超文本标记语言——HyperText Markup Language。 超文本…

【分布式配置中心】聊聊Apollo的安装与具体配置变更的原理

【管理设计篇】聊聊分布式配置中心 之前就写过一篇文章,介绍配置中心,但是也只是简单描述了下配置中心的设计点。本篇从apollo的安装到部署架构到核心原理进一步解读,大概看了下apollo的原理,感觉没有必要深究,所以就…

2023年“中银杯”四川省职业院校技能大赛“云计算应用”赛项样题卷③

2023年“中银杯”四川省职业院校技能大赛“云计算应用”赛项(高职组) 样题(第3套) 目录 2023年“中银杯”四川省职业院校技能大赛“云计算应用”赛项(高职组) 样题(第3套) 模块…

2024黑龙江省职业院校技能大赛暨国赛选拔赛应用软件系统开发赛项(高职组)赛题第1套

2024黑龙江省职业院校技能大赛暨国赛选拔赛 应用软件系统开发赛项(高职组) 赛题第1套 竞赛说明 目录 需要竞赛源码资料可私信博主! 竞赛说明 模块一:系统需求分析 任务1:制造执行MES—质量管理—质检标准&#xff…

FreeRTOS学习--49讲 事件标志位

事件标志位: 用一个bit位来表示事件是否发生,只有0(未发生)和1(已发生)两种状态 事件组:事件组是一组事件标志的集合,一组事件组包含了EventBites_t数据类型的变量,该变量高8未不能作为事件标志,用于存储控…

以一种访问权限不允许的方式做了一个访问套接字的尝试

python -m http.server 启动失败 原因是端口被占用,但是使用 netstat -ano|findstr 8000 却没发现占用,最后发现是hyper-v占用了,要给容器使用。 使用命令 netsh int ipv4 show dynamicport tcp可以查看TCP 动态端口范围的情况。 netsh int…

人机对话--关于意识机器

人机对话——关于意识机器 这段内容是我和《通义千问》的对话。这本身展示的是人工智能的效果,同时这里面的内容也有人工智能相关,与各位分享。 我:阿尼尔赛斯 《意识机器》这本书写的是什么? 通义千问: 阿尼尔赛斯…

❀My排序算法学习之冒泡排序❀

目录 冒泡排序(Bubble Sort):) 一、定义 二、算法原理 三、算法分析 时间复杂度 算法稳定性 算法描述 C语言 C++ 算法比较 插入排序 选择排序 快速排序 归并排序 冒泡排序(Bubble Sort):) 一、定义 冒泡排序(Bubble Sort),是一种计算机科学领域的较简单…

【北亚数据恢复】mysql表被truncate,表数据被delete的数据恢复案例

云服务器数据恢复环境: 华为ECS云服务器,linux操作系统,mysql数据库(innodb引擎)。作为网站服务器使用。 云服务器故障: 在执行mysql数据库版本更新测试时,误将本应该在测试库上执行的sql脚本执…

渗透测试计划模板

引言 1.1 目的 1.2 范围 1.3 参考文档 1.4 术语和定义 系统概述 2.1 系统描述 2.2 系统架构 2.3 技术栈 2.4 相关方 目标与风险评估 3.1 目标设定 3.2 风险评估 3.3 风险优先级排序 测试方法与工具 4.1 黑盒测试方法 4.2 白盒测试方法 4.3 灰盒测试方法 4.4 常用渗透测试工具…

亚马逊云科技Amazon Q,一款基于生成式人工智能的新型助手

近日,亚马逊云科技宣布推出Amazon Q,这是一款基于生成式人工智能(AI)的新型助手,专为辅助工作而设计,可以根据您的业务量身定制。通过连接到公司的信息存储库、代码、数据和企业系统,可以使用Am…

个人游戏启动器 | 游戏数据库 playnite 折腾记录

环境:Windows 11 问题:使用平板串联PC游戏后,需要一个本地的PC启动器 解决办法:使用playnite搭配插件 背景:我是个单机游戏爱好者,因为某些原因,需要串流游玩,需要一个方便手柄操作的…

arkts状态管理使用(@State、@Prop、@Link、@Provide、@Consume、@objectLink和@observed)

一、状态管理 1.在声明式UI中,是以状态驱动视图更新: ①状态(State):指驱动视图更新的数据(被装饰器标记的变量) ②视图(View):基于UI描述渲染得到用户界面 注意: ①…

【零基础入门VUE】VueJS - 模板

✍面向读者:所有人 ✍所属专栏:零基础入门VUE专栏https://blog.csdn.net/arthas777/category_12537076.html 我们在前面的章节中学习了如何在屏幕上以文本内容的形式输出。在本章中,我们将学习如何在屏幕上以 HTML 模板的形式获取输出。 为了…

NLP常见问题

transformer中的attention为什么scaled?-CSDN博客 Transformer模型中的Feed-Forward层的作用_transformer feed-forward解释-CSDN博客 关于ChatGPT:GPT和BERT的差别(易懂版) Index - 算法工程师笔记 Transformer模型中,decod…