MySQL 复制通常不会对带宽造成很大的压力,但在5.1 版本引入的基于行的复制会比传统的基于语句的复制模式的带宽压力更大。你可以随意地停止或开始复制,并在不同的地理位置来分布数据备份,例如不同的数据中心。即使在不稳定的网络环境下,远程复制也可以工作。但如果为了保持很低的复制延迟,最好有一个稳定的、低延迟连接。
1.2 负载均衡通过 MySQL 复制可以将读操作分布到多个服务器上,实现对读密集型应用的优化,并且实现很方便,通过简单的代码修改就能实现基本的负载均衡。对于小规模的应用,可以简单地对机器名做硬编码或使用DNS轮询(将一个机器名指向多个IP 地址)。当然也可以使用更复杂的方法,例如网络负载均衡这一类的标准负载均衡解决方案,能够很好地将负载分配到不同的 MySQL服务器上。Linux 虚拟服务器(Linux Virtual Server,LVS)也能够很好地工作。
1.3 备份对于备份来说,复制是一项很有意义的技术补充,但复制既不是备份也不能够取代备份。
1.4 高可用性和故障切换复制能够帮助应用程序避免 MySQL 单点失败,一个包含复制的设计良好的故障切换系统能够显著地缩短宕机时间。
1.5 MySQL 升级测试这种做法比较普遍,使用一个更高版本的MySQL作为备库,保证在升级全部实例前,查询能够在备库按照预期执行。
二、 复制如何工作在详细介绍如何设置复制之前,让我们先看看 MySQL 实际上是如何复制数据的。
2.1 总的来说,复制有三个步骤;- 1 在主库上把数据更改记录到二进制日志(Binary Log)中(这些记录被称为二进制日志事件)。
- 2 备库将主库上的日志复制到自己的中继日志(Relay Log)中。
- 3 备库读取中继日志中的事件,将其重放到备库数据之上。
以上只是概述,实际上每一步都很复杂。下图更详细地描述了复制的细节。
第一步是在主库上记录二进制日志(稍后介绍如何设置)。在每次准备提交事务完成数据更新前,主库将数据更新的事件记录到二进制日志中。MySQL 会按事务提交的顺序而非每条语句的执行顺序来记录二进制日志。在记录二进制日志后,主库会告诉存储引擎可以提交事务了。
下一步。备库将主库的二进制日志复制到其本地的中继日志中。首先,备库会启动一个
工作线程,称为 I/O线程,I/O线程跟主库建立一个普通的客户端连接,然后在主库上启动一个特殊的二进制转储(binlog dump)线程(该线程没有对应的 SQL 命令),这个二进制转储线程会读取主库上二进制日志中的事件。它不会对事件进行轮询。 如果该线程追赶上了主库,它将进入睡眠状态,直到主库发送信号量通知其有新的事件产生时才会被唤醒,备库 I/O线程会将接收到的事件记录到中继日志中。
备库的 SQL 线程执行最后一步,该线程从中继日志中读取事件并在备库执行,从而实现备库数据的更新。当SQL 线程追赶上I/O线程时,中继日志通常已经在系统缓存中,所以中继日志的开销很低。SQL 线程执行的事件也可以通过配置选项来决定是否写入其自己的二进制日志中,它对于我们稍后提到的场景非常有用。
上图显示了在备库有两个运行的线程,在主库上也有一个运行的线程;和其他普通连接一样,由备库发起的连接,在主库上同样拥有一个线程。
这种复制架构实现了获取事件和重放事件的解耦,允许这两个过程异步进行。也就是说I/O线程能够独立于SQL 线程之外工作。但这种架构也限制了复制的过程,其中最重要的一点是在主库上并发运行的查询在备库只能串行化执行,因为只有一个SQL 线程来重放中继日志中的事件。后面我们将会看到,这是很多工作负载的性能瓶颈所在。虽然有一些针对该问题的解决方案,但大多数用户仍然受制于单线程。



