MySQL之复制(十三)

news2024/11/25 4:57:44

复制

复制的问题和解决方案

在主-主复制结构总写入两台主库

在这里插入图片描述

试图向两台主库写入并不是一个好主意,如果同时还希望安全地写入两台主库,会碰到很多问题,有些问题可以解决,有些则很难。一个专业人员可能需要经历大量的教训才能明白其中的不同。在MySQL5.0中,有两个变量可以用于帮助解决AUTO_INCREMENT自增主键冲突的问题:auto_increment_increment和auto_increment_offset。可以通过设置这两个变量来错开主库和备库生成的数字,这样可以避免自增列的冲突。但是这并不能解决所有由于同时写入两太主库所带来的问题;自增问题只是其中的一小部分。而且这种做法也带来了一些新的问题:

  • 1.很难在复制拓扑间作故障转移
  • 2.由于在数字之间出现间隙,会引起键空间的浪费
  • 3.只有在使用了AUTO_INCREMENT主键的时候才有用。有时候使用AUTO_INCREMENT列作为主键并不总是好主意

你也可以自己来生成不冲突的主键值。一种办法时创建一个多个列的主键,第一列使用服务器ID值。这种办法很好,但却使得主键的值变得更大,会对InnoDB二级索引键值产生多重影响。也可以使用只有一列的主键,在主键的高字节位存储服务器ID。简单地左移法(除法)和加法就可以实现。例如,使用的是无符号BIGINT(64位)的高8位来保存服务器ID,可以按照如下方法在服务器15上插入值11:

mysql>INSERT INTO test(pk_col, ...) VALUE ((15 << 56) + 11, ....)

如果想把结果转换为二进制,并将其填充64位,其效果显而易见:

mysql>SELECT LPAD(CONV(pk_col, 10,2), 64 , '0') FROM test;

该方法的缺点是需要额外的方式来产生键值,因为AUTO_INCREMENT无法做到这一点。不要在INSERT语句中将常量15替换为@@server_id,因为这可能在备库产生不同的结果。还可以使用MD5()或者UUID()等函数来获取伪随机数,但这样做性能可能会很差,因为它们产生的值较大,并且本质上是随机的,这尤其会影响到InnoDB(除非是在应用中产生之,否则不要使用UUID(),因为基于语句的复制模式下UUID()不能正确复制)。
这个问题很难解决,通常推荐重构应用程序,以保证只有一个主库是可写的。谁能想得到呢?

过大的复制延迟

复制延迟是一个很普遍的问题。不管怎么样,最好在设计应用程序时能够让其容忍备库出现延迟,如果系统在备库出现延迟时就无法很好地工作,那么应用程序也许就不应该用到复制。但是也有一些办法可以让备库跟上主库。MySQL单线程复制的设计导致备库的效率相当低下。即使备库有很多磁盘、CPU或者内存,也会很容易落后于主库。因为备库的单线程通常只会有效地使用一个CPU和磁盘。而事实上,备库通常哦都会和主库使用相同配置的机器。
备库上的锁同样也是问题。其他在备库运行的查询可能会阻塞主复制线程,因为复制时单线程的,复制线程在等待时将无法做别的事情。复制一般有两种产生延迟的方式:突然产生延迟然后再跟上,或者稳定的延迟增大。前一种通常是由于一条运行很长的查询导致的,而后者即使在没有长时间运行的查询时也会出现。不幸的是,目前我们还没那么容易确定备库是否接近其容量上限。正如之前提到的。如果负载总是保持均匀的,备库在负载达到99%时和其负载10%的时候表现的性能相同,但一旦达到100%时就会突然产生延迟。但实际上负载不太可能很稳定,所以当备库接近写容量时,就可能在尖峰负载时看到复制延迟的增加。当备库无法跟上时,可以记录备库上的查询并使用一个日志分析工具找出哪里满了。不要依赖于自己的直觉,也不要基于查询在主库上的查询性能进行判断,因为主库和备库性能特征很不相同。最好的分析办法是暂时在备库上打开慢查询日志记录,然后使用pt-query-digest工具来分析。如果打开了log_slow_slave_statements选项,在标准的MySQL慢查询日志能够记录MySQL5.1及更新的版本中复制线程执行的语句,这样就可以找到在复制时哪些语句执行慢了。Percona Server和MariaDB允许开启或进制该选项而无须重启服务器。
除了购买更快的磁盘和CPU(固态硬盘能够提供极大的帮助),备库没有太多的调优空间。大部分选项都是禁止某些额外的工作以减少备库的负载。一个简单的办法是配置InnoDB,使其不要那么频繁地刷新磁盘,这样事务会提交得更快些。可以通过设置innodb_flush_log_at_trx_commit得值为2来上限。还可以在备库上禁止二进制日志记录,把innodb_locks_unsafe_for_binlog设置为1,并把MyISAM得delay_key_write设置为ALL.但是这些设置以牺牲安全换取速度。如果需要将备库提升为主库,记得把这些选项设置回安全的值

不要重复写操作中代价较高的部分

重构应用程序并且/或者优化查询通常是最好的保持同步的办法。尝试去最小化系统中重复的工作。任何主库上昂贵的写操作都会在每一个备库上重放。如果可以把工作转移到备库,那么久只有一台备库需要执行,然后我们可以把写的结果回传到主库,例如通过执行LOAD DATA INFILE.
举个例子,假设有一个大表,需要汇总到一个小表中用于日常的工作:

mysql>REPLACE INTO main_db.summary_table(col1, col2, ...) SELECT col1, sum(col2, ...) FROM main_db.enormous_table GROUP BY col1;

如果在主库上执行查询,每个备库将同样需要执行庞大的GROUP BY 查询。当进行太多这样的操作时,备库将无法跟上。把这些工作转移到一些备库上也许会有帮助。在备库上创建一个特别保留的数据库,用于避免和从主库上复制的数据产生冲突。可以执行以下查询:

mysql>REPLACE INTO summary_db.summary_table(col1, col2, ...) SELECT col1, sum(col2,...) FROM main_db.enormous_table GROUP BY col1;

现在可以执行SELECT INTO OUTFILE,然后再执行LOAD DATA INFILE,将结果集加载到主库中。现在重复工作被简化为LOAD DATA INFILE操作。如果有N个备库,就节约了N-1次庞大的GROUP BY 操作。
该策略的问题是需要处理陈旧数据。有时候从备库读取的数据和写入主库的数据很难保持一致。如果难以在备库上读取数据,依然能够简化并节省备库工作。如果分离查询的REPLACE和SELECT部分,就可以把结果返回给应用程序,然后将其差人到主库中。首先,在主库执行如下查询:

mysql>SELECT col1, sum(col2,...) FROM main_db.enormous_table GROUP BY col1;

然后为结果集的每一行重复执行如下语句,将结果插入到汇总表中:

mysql>REPLACE INTO main_db.summary_table (col1, col2,...) VALUES(?,?,...)

这种方法再次避免了在备库上执行查询中的GROUP BY 部分。将SELECT和REPLACE分离后意味着查询的SELECT操作不会在每一台备库上重放。这种通用的策略——节约了备库上昂贵的写入操作部分——在很多情况下很有帮助:计算查询的结果代价很昂贵

在复制之外并行写入

另一种避免备库严重延迟的办法是绕过复制。任何在主库上的写入操作必须在备库串行化。因此有理由认为"串行化写入"不能充分利用资源。所有写操作都应该从主库传递到备库码?如果把备库优先的串行写入容量留给哪些真正需要通过复制进行的写入?
这种考虑有助于对写入进行区分。特别是,如果能确定一些写入可以轻易地在复制之外执行,就可以并行化这些操作以利用备库的写入容量。一个很好的例子是之前讨论过的数据归档。OLTP归档需求通常是简单的单行操作。如果只是把不需要的记录从一个表转移到另一个表,就没有必要将这些写入复制到备库。可以禁止归档查询记录到二进制日志中,然后分别在主库和备库上单独执行这些归档查询。自己复制数据到另外一台服务器,而不是通过复制,这听起来有些疯狂,但却对一些应用有意义,特别是如果应用是某些表的唯一更新源。复制的瓶颈通常集中在小部分表上,如果能在复制之外单独处理这些表,就能够显著地加快复制。

为复制线程预取缓存

如果有正确的工作负载,就能通过预先将数据读入内存中,以受益于在备库上的并行IO所带来的好处。这种方式并不广为人知。大多数人不会使用,因为除非有正确的工作负载特性和硬件配置,否则可能没有任何用处。上面讨论的其他几种变通方式通常是更好的选择,并且有更多的方法来应用它们。但是我们直到也有小部分应用会受益于数据预取。
有两种可行的实现方法。一种是通过程序实现,略微比备库SQL线程提前读取中继日志,并将其转换为SELECT语句执行。这会使得服务器将数据从磁盘加载到内存中,这样当SQL线程执行到相应的语句时,就无须从磁盘读取数据。事实上,SELECT语句可以并行地执行,所以可以加速SQL线程的串行IO.当一条语句正在执行时,下一条语句需要的数据也正在从磁盘加载到内存中。
如果满足下面这些条件,预取可能会有效:

  • 1.复制SQL线程是IO密集型的,但备库服务器并不是IO密集型的.一个完全的IO密集型服务器不会受益于预取,因为它没有多余的磁盘性能来提供预取
  • 2.备库有多个硬盘驱动器,也许8个或者更多
  • 3.使用的是InnoDB以前宁,并且工作集远不能完全加载到内存中

一个受益于预读取的例子是随机单行UPDTE语句,这些语句通常在主库上高并发执行。DELETE语句也可能受益于这种方法,但INSERT语句则不太可能会——尤其是当顺序插入时——因为前一次插入已经使索引"预热"了。如果表上有很多索引,同样无法预取所有将要被修改的数据。UPDATE语句可能需要更新所有索引,但SELECT语句通常只会读取主键和一个二级索引。UPDATE语句依然需要去读取其他索引的数据以进行更新。在多索引表上这种方法的效率会降低。这种技术并不是"银弹",有很多原因会导致其不能工作,甚至适得其反。只有在清楚硬件和操作系统的状况时才能尝试这种方法。我们直到有些人利用这种办法将复制速度提升了300%到400%,但也尝试过很多次,并发现这种办法常常无法工作。正确地设置参数非常重要,但并没有绝对正确的参数组合。
mk-slave-perfetch是Maatkit种的一款工具,该工具实现了提到的预取策略。mk-slave-prefetch本身有很多复杂的策略以保证其尽可能多的场景下工作,但缺点是它实在太复杂并且需要许多专业知识来使用,另一款工具是Anders Karlsson的slavereadahead工具。
另一种方法是在InnoDB内部实现的。它可以允许设置事务为特殊的模式,以允许InnoDB执行"假"更新。因此可以使用一个程序来执行这些加更新,这样复制线程就可以更快地执行真正的更新。Percona Server为一个非常流行的互联网网络应用单独开发了该功能。可以去检查一下此特性现在的状况。
如果正在考虑这项技术,可以从一个熟悉其工作原理及可用选项的专家那里获得很好的建议,这应该作为其他方法都不可行时最后的解决办法

来自主库的过大的包

另一个难以追踪的问题是主库的max_allowed_packet值和备库的不匹配。在这种情况下,主库可能会记录一个备库认为过大的包。当备库获取到该二进制日志事件时,可能会碰到各种各样的问题,包括无限报错和充实,或者中继日志损坏

受限制的复制带宽

如果使用受限的带宽进行复制,可以开启备库上的slave_compressed_protocol选项。当备库连接主库时,会请求一个被压缩的连接——和MySQL客户端使用的压缩连接一样。使用的压缩引擎是zlib,测试表明它能将文本类型的数据压缩到大约其原始大小的三分之一。其代价是需要额外的CPU时间,包括在主库上压缩数据和在备库上解压数据。
如果主库和备库间的连接是慢速连接,可能需要将分发主库和备库分布在同一地点。这样就只有一台服务器通过慢速连接和主库相连,可以减少链路上的带宽负载以及主库的CPU负载

磁盘空间不足

复制有可能因为二进制日志、中继日志或临时文件将磁盘撑满,特别是在主库上执行了LOAD DATA INFILE查询并在备库开启了log_slave_updates选项。延迟越严重,接收到但尚未执行的中继日志会占用越多的磁盘空间。可以通过监控磁盘并设置relay_log_space选项来避免这个问题

复制的局限性

MySQL复制可能失败或者不同步,不管有没有报错,这是因为其内部的限制导致的。大量的SQL函数和编程实践不能被可靠地复制。很难确保应用代码里不会出现这样或那样的问题,特别是应用或者团队非常庞大的时候。另外一个问题是服务器的bug,虽然听起来很消极,但大多数MySQL的主版本都存在着历史遗留的复制Bug。特别是每个主版本的第一个版本。诸如存储过程这样的新特性常常会导致更多的问题。
MySQL复制非常复杂,应用程序越复杂,你就需要越小心。但是如果学会了如何使用,复制会工作得很好。

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

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

相关文章

2024 年值得推荐的 10 款 iPhone 数据恢复软件

iPhone 从来都不是一个简单的打电话电话。它就像一台微型电脑&#xff0c;让我们互相联系、拍照、拍视频、发邮件、看文档、看书。然而&#xff0c;随着它成为日常生活的必需品&#xff0c;我们总是容易因各种原因丢失数据&#xff0c;如删除、恢复出厂设置、iOS 错误、文件同步…

Day11 —— 大数据技术之Spark

Spark快速入门系列 Spark的概述什么是Spark&#xff1f;Spark的主要特点Spark的主要组件 Spark安装Spark三种运行模式Spark Standalone架构Spark Standalone的两种提交方式Spark On YARN架构 RDD算子转化算子行动算子 Spark RDDRDD的创建从对象集合创建RDD从外部存储创建RDD Sp…

Apollo9.0 PNC源码学习之Planning模块(一)—— 规划概览

0 前言 规划本质就是搜索问题,数学角度来看就是寻找函数最优解 规划模块复杂的就是相关的逻辑处理和过程计算 对于规划的三维问题,目前解决方案:降维+迭代 将SLT问题分解为ST和SL二维优化问题:在一个维度优化之后,再另一个维度再进行优化,最后整合成三维的轨迹。 虽然降…

Linux常用命令(15)—grepsed命令(有相关截图)

写在前面&#xff1a; 最近在学习Linux命令&#xff0c;记录一下学习Linux常用命令的过程&#xff0c;方便以后复习。仅供参考&#xff0c;若有不当的地方&#xff0c;恳请指正。如果对你有帮助&#xff0c;欢迎点赞&#xff0c;关注&#xff0c;收藏&#xff0c;评论&#xf…

【2024.6.23】今日 IT 速递 | 亚布力创新年会热点新闻盘点

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌…

细胞核的分割与分类模型·hover net| 补充文档

小罗碎碎念 这期推文算是hover net系列的一个补充文档&#xff0c;把几个非常重要的脚本拿出来单独做了一个分析&#xff0c;感兴趣的自取。 extract_patches.pyconfig.pydataset.pyopt.pyrun_infer.py 一、extract_patches.py 1-1&#xff1a;加载和处理图像数据集 注意 da…

53【场景作图】纵深感

1 想清楚什么是前 什么是后 如果背景虚化,就不要处理地很平面,如果很平面,就留一个清晰的边缘 2 重叠 遮挡 被遮挡的物体会更远

如何让表格标题栏具有粘性?

让表格标题栏具有粘性 什么意思呢&#xff1f; 就是当表格的内容&#xff08;行数&#xff09;比较多的时候&#xff0c; 滚动屏幕&#xff0c;看下面的内容的时候&#xff0c; 表格标题栏可以一直显示在屏幕最上方&#xff0c; 以前呢&#xff0c; 我会通过JSCSS 的 pos…

开发一个python工具,pdf转图片,并且截成单个图片,然后修整没用的白边及循环遍历文件夹全量压缩图片

今天推荐一键款本人开发的pdf转单张图片并截取没有用的白边工具 一、开发背景&#xff1a; 业务需要将一个pdf文件展示在前端显示&#xff0c;但是基于各种原因&#xff0c;放弃了h5使用插件展示 原因有多个&#xff0c;文件资源太大加载太慢、pdf展示兼容性问题、pdf展示效果…

基于nsight_compute进行kernel性能分析

当利用nsight进行性能分析时&#xff0c;当涉及到内核级别的性能分析时&#xff0c;nvidia提供了系统级别(nsight system)&#xff0c;和内核级别的性能分析工具&#xff08;nsight compute&#xff09;。 其中&#xff0c;内核级别的性能分析&#xff0c;可以检查kernel实现的…

apollo规划架构

算法的基本架构 我们在最开始直接给出规划决策算法架构框图&#xff0c;然后一一介绍每个框图结构的细节&#xff1a; 模块的入口是 PlanningComponent&#xff0c;在 Cyber 中注册模块&#xff0c;订阅和发布消息&#xff0c;并且注册对应的 Planning 类。Planning 的过程之前…

基于SpringBoot+Vue教材订购系统设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f; 感兴趣的可以先收藏起来&#xff0c;…

DNF手游攻略:云手机辅助流光星陨刀详细攻略大全!

DNF手游中&#xff0c;流光星陨刀是鬼剑士的专属神器之一&#xff0c;拥有快速的攻击速度和优秀的物理与法术攻击属性&#xff0c;因其出色的性能和未来升级的潜力&#xff0c;成为广大玩家关注的焦点。 流光星陨刀的背景与起源 流光星陨刀作为鬼剑士的标志性武器之一&#xf…

使用 Ubuntu x86_64 平台交叉编译适用于 Linux aarch64(arm64) 平台的 QT5(包含OpenGL支持) 库

使用 Ubuntu AMD64 平台交叉编译适用于 Linux ARM64 平台的 QT5(包含 OpenGL/WebEngine 支持) 库 目录 使用 Ubuntu AMD64 平台交叉编译适用于 Linux ARM64 平台的 QT5(包含 OpenGL/WebEngine 支持) 库写在前面前期准备编译全流程1. 环境搭建2. 复制源码包并解压&#xff0c;创…

论文《Universal Graph Convolutional Networks》笔记

【UGCN】论文提出一个基本问题&#xff0c;即是否不同的网络结构属性应该采用不同的传播机制。通过实验发现&#xff0c;对于完全同配性、完全异配性和随机性的网络&#xff0c;1-hop、2-hop和k-nearest neighbor&#xff08;kNN&#xff09;邻居分别更适合作为信息传播的邻域。…

stm32学习笔记---GPIO输出(理论部分)

目录 GPIO通用输入输出口 GPIO的基本结构 I/O端口位的基本结构 输入部分 输出部分 推挽模式 开漏模式 GPIO的8种工作模式 STM32手册GPIO和AFIO大致介绍 STM32外部的设备和电路 声明&#xff1a;本专栏是本人跟着B站江科大的视频的学习过程中记录下来的笔记&#xff0…

CISP-PTE综合靶机-WinServer2003

1.收集网站的地址和开放的端口,完成前期信息收集。10分 2.访问站点,找出站点的敏感文件,利用返回数据找到相关敏感信 息,完成网站结构的信息收集。10分 3.利用文件包含漏洞读取敏感文件,找出数据库连接凭证,利用此 凭证连接数据库。10分 4.网站后台提权:找出后台管理员登…

Attention系列总结-粘贴自知乎

1. 梦想做个翟老师&#xff1a;阿里&#xff1a;Behavior Sequence Transformer 解读48 赞同 7 评论文章 优点:捕捉用户行为历史序列中的顺序信息。w2v也是捕捉用户序列信息的,本质差异在于啥&#xff1f; 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff0…

STM32CubeIDE提示找不到头文件(No such file or directory)的解决办法

0 前言 最近在使用STM32CubeIDE时&#xff0c;发现为工程添加了头文件路径&#xff0c;但编译的时候还是报错&#xff0c;提示找不到头文件&#xff1a; 1 解决办法 1.1 为工程添加头文件路径 右键我们的工程&#xff0c;然后添加头文件路径&#xff08;最好是相对路径&am…

Vue3+TypeScript项目实战——打造雨雪交加的智慧城市

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 ⚡开源项目&#xff1a; rich-vue3 &#xff08;基于 Vue3 TS Pinia Element Plus Spring全家桶 MySQL&#xff09; &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全干发展 &#x1…