在MySQL主从复制结构中,随着连接至数据源的副本数增加,尽管负载相对较小,但仍会增加负载,因为每个副本都要和数据源建立一个客户端连接。此外,由于每个副本都必须接收到源二进制日志的完整副本,源上的网络负载也可能增加并形成瓶颈。
如果您使用大量副本连接到一个源,并且该源还忙于处理请求(例如,作为扩展方案的一部分),则您可能希望提高复制过程的性能。
改善复制过程性能的一种方法是创建一个更深的复制结构,使源只需复制到一个副本,而其他副本则连接到这个主副本以满足它们各自的复制需求。结构如下:
+-------------------+| MySQL Source 1 |+-------------------+↓ (复制)+-------------------+| MySQL Source 2 |+-------------------+↓ (复制) ↓ (复制) ↓ (复制)
+---------+ +---------+ +---------+
| Replica1| | Replica2| | Replica3|
+---------+ +---------+ +---------+
服务器MySQL Source 1复制到服务器MySQL Source 2,后者又复制到服务器MySQL Replica 1、MySQL Replica 2和MySQL Replica 3。
要使之工作,您必须按以下方式配置MySQL实例:
-
Source 1 是主源,所有更改和更新都写入数据库。两个源服务器都启用了二进制日志记录,这是默认设置。
-
Source 2 是服务器Source 1的副本,为复制结构中余下的副本提供复制功能。Source 2是唯一允许连接到Source 1的机器。Source 2启用了
--log-slave-updates
选项(这是默认设置)。通过此选项,从Source 1收到的复制指令也会写入到Source 2的二进制日志中,然后再被复制到真正的副本。 -
Replica 1、Replica 2 和 Replica 3 作为Source 2的副本,复制Source 2的信息,实际上包括记录在Source 1上的更新。
上述解决方案减少了主源上的客户端负载和网络接口负载,应该可以提高作为直接数据库解决方案时主源的整体性能。
如果你的副本跟不上源的复制进程,有多个选项可用:
-
尽可能将中继日志和数据文件放在不同的物理驱动器上。为此,请设置
relay_log
系统变量来指定中继日志的位置。 -
如果二进制日志文件和中继日志文件的硬盘I/O活动较重是一个问题,考虑增加
rpl_read_size
系统变量的值。此系统变量控制从日志文件读取的最小数据量,增加它可能会减少文件读取和I/O停顿,当文件数据未被操作系统当前缓存时。注意,每个从二进制日志和中继日志文件读取的线程,包括源上的转储线程和副本上的协调线程,都会为其分配一个相当于此值大小的缓冲区。因此,设置较大的值可能会影响服务器的内存消耗。 -
如果副本显著慢于源,您可能希望将复制不同数据库的责任分配给不同的副本。。
-
如果您的源使用事务,并且您对副本上的事务支持不关心,请在副本上使用MyISAM或其他非事务引擎。
-
如果您的副本不用作源,并且您已经有了一个保证在故障发生时可以启用源的潜在解决方案,则可以在副本上禁用系统变量
log_replica_updates
(从MySQL 8.0.26开始)或log_slave_updates
(在MySQL 8.0.26之前)。这样可以防止“愚蠢”的副本也将它们执行过的事件记录到自己的二进制日志中。 -
配置replica_parallel_workers 和replica_parallel_type开启MySQL复制线程的并行复制。