暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

MySQL 主从复制的问题及解决方案

张芝 2024-09-06
61

复制功能是构建 MySQL 的大规模、高性能的基础,也就是所谓的 “水平扩展” 架构。我们可以通过为服务器配置一个或多个备库。同时,复制也是高可用性、可扩展性、灾难恢复、备份以及数据仓库等工作的基础。MySQL主从基本原理,主要形式以及主从同步延迟原理 (读写分离)导致主库从库数据不一致问题的及解决方案。


泽拓昆仑Klustron的fullsync提供了严格健壮的数据同步机制,可以确保在主备节点同时断电、宕机等故障情况下,数据不丢失损坏,在性能和可靠性方面全面优于 MySQL semisync replication。详见:昆仑分布式数据库存储集群 Fullsync 机制


原文作者:CSDN博主[程序猿进阶]


关键词:MySQL、主从复制、高可用、备份恢复、Fullsync



01  
复制概述

复制解决的基本问题是让一台服务器的数据与其他服务器保持同步。一台主库的数据可以同步到多台备库上,备库本身也可以被配置成另外一台服务器的主库。通过复制可以将读操作指向备库来获得更好的读扩展,但对于写操作,除非设计得当,否则并不适合通过复制来扩展写操作。当使用一主多备架构时,可能会造成一些浪费,因为本质上它会复制大量不必要的重复数据。

MySQL 支持两种复制方式:基于行的复制和基于语句的复制(逻辑复制)。这两种方式都是基于在主库上记录二进制日志、在备库上重放日志的方式来实现异步的数据复制。这就导致在同一时间点备库上的数据可能与主库存在不一致,并且无法保证主备之间的延迟。一些大的语句可能导致产生几秒、几分钟甚至几小时的延迟。

MySQL 大部分是向后兼容的,新版本的服务器可以作为老版本的服务器的备库,但是反过来是不可行的,因为它可能无法解析新版本所采用的新的特性或语法,另外所使用的二进制文件的格式也可能不相同。

复制通常不会增加主库的开销,主要是启用二进制日志带来的开销,但出于备份或及时从崩溃中恢复的目的,这点开销也是必要的。除此之外,每个备库也会对主库增加一些 I/O 开销,尤其当备库请求从主库读取旧的二进制日志文件时。另外锁竞争也可能阻塞事务的提交。


02  
复制工作机制【异步复制】

复制分为以下三个步骤

  1. 在主库上把数据更改记录到二进制日志(Binary Log)中(这些记录被称为二进制日志事件)。MySQL 会按事务提交的顺序而非每条语句的执行顺序来记录二进制日志。在记录二进制日志后,主库会告诉存储引擎可以提交事务了。

  2. 备库将主库上的二进制日志复制到自己的中继日志(Relay Log)中。【更多细节】备库会启动一个工作线程,称为 I/O线程,I/O线程跟主库建立一个普通的客户端连接,然后在主库上启动一个特殊的二进制转储(binlog dump)线程,这个二进制转储线程会读取主库上二进制日志事件。如果该线程追赶上主库,它将进入睡眠状态,直到主库发送信号量通知其有新的事件产生时才会被唤醒,备库 I/O 线程会将接收到的事件记录到中继日志中。
  3. 备库读取中继日志中的事件,将其重放到备库数据之上。

这种复制架构实现了获取事件和重放事件的解耦,允许这两个过程异步进行。也就是说 I/O 线程能够独立于 SQL 线程之外的工作。最重要的问题是主库上并发运行的查询在备库只能串行化执行,因为只有一个 SQL 线程来重放中继日志的事件。


03  
复制的用途和条件

主从复制的用途:
  • 实时灾备,用于故障切换;
  • 读写分离,提供查询服务;
  • 备份,避免影响业务。

主从部署必要条件:
  • 主库开启binlog日志(设置log-bin参数);
  • 主从server-id不同;
  • 从库服务器能连通主库。


04  
复制的问题和解决方案

4.1 MySQL 数据库从库同步的延迟问题

复制延迟是一个很普遍的问题,最好在设计应用程序时能够让其容忍备库出现延迟。如果系统在备库出现延迟时就无法很好地工作,那么应用程序也许就不应该用到复制。但也有办法可以让备库跟上主库。

MySQL 单线程复制的设计导致备库通常只会有效地使用一个 CPU 和磁盘,效率相当低下。而事实上,备库通常都会和主库使用相同配置的机器。同时备库上的锁也是问题,运行的查询可能会阻塞复制线程。因为复制是单线程的,复制线程在等待时将会无法做别的事。

复制一般有两种产生延迟的方式:突然产生延迟然后再跟上,或者稳定的延迟增长。前一种通常是由于一条运行很长时间的查询导致,而后者即使在没有长时间运行的查询时也会出现。当备库无法跟上时,可以记录备库上的查询并使用一个日志分析工具找出哪里慢了。最好的分析办法是暂时在备库上打开慢查询日志记录,然后使用 pt-query-digest 工具来分析。如果打开了 log_slow_slave_statements 选项,在标准的 MySQL 慢查询日志能够记录 MySQL5.1 及更新的版本中复制线程执行的语句,这样就可以找到在复制时那些语句执行慢了。

4.1.1 解决方案一:

除了购买更快的磁盘和CPU(固态磁盘能够提供极大的帮组)备库没有太多的调优空间。大部分选项都是禁止某些额外的工作以减少备库的负载。一个简单的办法是配置 InnoDB,使其不要频繁地刷新磁盘,这样事务会提交得更快些。如下:

  • 默认值1的意思是每一次事务提交或事务外的指令都需要把日志写入(flush)硬盘,这是很费时的。
  • 特别是使用电池供电缓存(Battery backed up cache)时。
  • 设成2对于很多运用,特别是从MyISAM表转过来的是可以的,它的意思是不写入硬盘而是写入系统缓存。
  • 日志仍然会每秒flush到硬盘,所以你一般不会丢失超过1-2秒的更新。
  • 设成0会更快一点,但安全方面比较差,即使MySQL挂了也可能会丢失事务的数据。
  • 而值2只会在整个操作系统挂了时才可能丢数据。
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论