MySQL 复制:最佳实践与注意事项
MySQL 提供了多种选项来配置复制,但面对如此多的选择,你如何确保自己做得正确?
复制是为你的 MySQL 数据库提供更高可用性的重要第一步。一个配置良好的复制架构可能成为数据高可用性与复杂管理之间的差异。在 PlanetScale,我们支持数十万个数据库集群,这些集群全部使用复制来实现高可用性,因此我们在这一领域积累了丰富经验!
在本文中,我们将探讨有关复制的一些最佳实践,无论是本地复制还是跨远距离复制。
使用 Active/Passive 配置
在主动/被动(Active/Passive)模式下进行复制时,一个 MySQL 服务器作为主服务器(源服务器),其他所有服务器都是只读的副本,从这个主服务器获取数据。
在此配置中,副本服务器可以用来处理只读查询,但所有写操作都必须发送到主服务器。这种方式可以将读负载分散到所有副本服务器上,但需要注意的是,当使用默认的**异步复制模式**(后文会详细讲解)时,数据从写入主服务器到可以在副本上访问可能会有一定延迟。在设计应用程序时必须考虑到这一点。
另一种配置是主动/主动(Active/Active)模式,这种模式下多个服务器都可以同时用来处理读和写操作。
主动/主动听起来很不错,因为它能让两个服务器处理写请求,但实际上,每个服务器都在处理另一个服务器的查询负载,因此写负载分布更多是表面现象。此外,服务器之间的无缝切换可能会导致冲突,因为 MySQL 本身没有内置冲突解决逻辑。如果产生冲突,任何一方都无法作为数据恢复的权威来源,而不导致大量数据丢失。
我们始终建议使用主动/被动(Active/Passive)配置进行复制,并在需要更高的数据库吞吐时使用分片(Sharding)。
注意: 如果你对分片感兴趣,可以观看我们的技术讲座,在其中解决方案架构师 Liz van Dijk 深入讲解了分片。
使用 GTID
全局事务标识符(Global Transaction Identifiers,简称 GTID)是在复制环境中为给定事务分配的唯一 ID。
默认情况下,副本服务器会读取主服务器上的二进制日志文件,并根据文件中的位置来追踪已处理的记录。副本处理事务时,文件位置会不断更新,以表示已经处理到的点。然而,这种机制较为脆弱,因为如果主服务器崩溃并需要恢复日志,则可能引发问题。
启用 GTID 后,每个事务都会被分配一个唯一标识符,副本服务器可通过这个标识符确定某个事务是否已处理。
每个 GTID 是一个 UUID(唯一标识字符串),由源服务器的 ID 和一个自动递增的整数组成,格式如:14a54b2f-2ad0-43b6-b803-72b5d7151d3b:1
。随着事务在主服务器上的处理,UUID 保持不变,但 ID 会持续增长。当副本处理来自主服务器的事务时,GTID 或 GTID 范围(如 14a54b2f-2ad0-43b6-b803-72b5d7151d3b:1-10
)会存储在 gtid_executed
表中。
这种机制可以显著减少数据不一致的风险,例如某些事务未被处理或被多次处理的情况。
使用正确的复制模式
MySQL 提供两种不同的复制模式,你需要了解它们的行为以确保选择适合你的环境的模式。
默认情况下,MySQL 使用异步复制。在这种模式下,事务在主服务器上处理后会被发送到副本服务器,副本会独立读取并处理这些事务。主服务器不会验证环境中的任何副本是否处理了事务。
另一种复制模式是 MySQL 支持的**半同步复制**,需通过插件启用。
启用半同步复制后,事务会先在主服务器接收并处理,然后发送到副本服务器。主服务器会等待至少一台副本服务器确认事务已接收后再响应客户端请求。好处是数据一致性更高,因为环境中至少有两台数据库服务器拥有数据,但这会带来一些额外的响应时间开销。PlanetScale 使用半同步复制来实现区域内的数据库稳定性。
启用半同步模式后,还可以进行一些额外配置,例如调整服务器的等待时长。
默认情况下,主服务器会等待副本服务器在 10 秒内确认事务。这一值是可修改的,如果你依赖半同步复制来保证数据一致性,可以将此值调高。我们通常将超时值设置得非常高,以确保数据始终一致。
值得一提的是,这两种模式可以混合使用。
例如,如果你希望保证某一特定服务器始终拥有数据库的最新副本,同时希望拥有其他副本服务器来增强弹性,可以将其中一台副本配置为半同步模式,其他副本则使用异步模式。这样,当数据写入主服务器时,主服务器会确保启用了半同步的副本接收到事务后再响应客户端。而其他副本将根据需求自行追赶最新状态。在灾难场景下(后文会进一步讨论),这可以帮助你轻松识别最佳的恢复候选服务器。
理解这两种复制模式的区别,可以让你在业务需求上做出更好的选择。
日志存储
如前文所述,副本服务器会读取源服务器上的二进制日志文件以获取数据。
默认情况下,这些日志文件存储在与数据库相同的磁盘上。显然,对于繁忙的数据库来说单盘存储可能成为瓶颈,因为单个磁盘同时处理数据库读写以及读取二进制日志进行复制的任务。
因此,更好的做法是将二进制日志存储在与数据库不同的磁盘上。
这种做法还可以节省云环境中的成本,因为云中的免费磁盘可能会有硬性 IOPS 限制。
监控复制
所有基础设施都需要监控以主动发现问题,复制也不例外。
如果不进行监控,你可能无法知道配置完成后数据是否真的被复制。如果出现问题,无法及时发现和处理可能会引发更大的故障。
SolarWinds 数据库性能监控(前身为 VividCortex)是一个流行的数据库监控解决方案,也支持复制监控。在 PlanetScale,我们使用 Prometheus 来监控复制情况及其他集群相关指标。
不论你使用哪种解决方案,请确保问题发生时可以通知适当的人员,以便在问题酿成更大的危害之前解决问题。
创建故障转移策略
软硬件故障是不可避免的,因此提前规划好故障转移策略可以最大限度地减轻故障带来的痛苦。
使用复制的主要好处之一是提高弹性,因为任何时间内都有多台服务器在线存储数据。你的团队应该提前准备好应对主服务器故障的策略。以下是一个未计划的故障转移示例:
- 确保故障的主服务器不会意外重新上线,否则可能导致复制问题。
- 确定你要选择的副本作为新的主服务器,并取消其
read_only
选项。如果启用了半同步复制,这通常是启用了插件的副本。 - 更新应用程序,将查询指向新的主服务器。
- 更新其他副本服务器以从新的主服务器开始复制。
跨数据中心复制时的注意事项
在云环境中,你可以将服务部署到几乎全球任何地方,包括数据库。
每个云服务商通常由若干地理区域组成。在这些区域内还有多个数据中心,这些数据中心之间足够接近以应对较小规模的灾难,但也足够远以应对较大灾难。这些数据中心被称为可用区(Availability Zones,简称 AZs)。
如果可能,将数据库复制到其他物理位置是最佳实践,但需要额外注意一些事项。
例如,传输数据所需的时间是一个重要考虑因素。
由于网络流量需要跨较远距离传输,跨数据中心的复制会引入额外的副本延迟。幸运的是,同一区域内的可用区之间通常延迟较低。例如,AWS 声称同一区域内的可用区之间延迟通常为单位数毫秒。
但跨区域的延迟则大得多。
截至本文撰写时,cloudping.co 报告 us-east-1 与 us-west-1 之间的延迟超过 60 毫秒。复制本身已经会产生一定的时间差(写入主服务器与副本写入之间的延迟),而跨区域复制会进一步加剧这种差异。
因此,跨区域复制应以异步模式进行,以便减少对请求处理的不必要延迟。
结论
仅仅了解配置复制的选项是不够的。理解如何为这些选项进行最佳配置,可以显著改善你的 MySQL 集群的运行效率及数据服务质量。
关注公众号:程序新视界,一个让你软实力、硬技术同步提升的平台
除非注明,否则均为程序新视界原创文章,转载必须以链接形式标明本文链接
本文链接:https://choupangxia.com/2025/09/13/mysql-replication-best-practices-and-considerations/