1. 概述1.1. 复制解决的基本问题是让一台服务器的数据与其他服务器保持同步1.2. 在源服务器(source server)上,任何数据修改和数据结构变更的事件(event)都会被写入日志文件中1.3. 副本服务器从源服务器上的日志文件中读取这些事件并在本地重放执行1.4. 一个异步处理的过程1.4.1. 不能保证副本服务器上的数据是最新的1.4.2. 复制延迟(副本数据和最新数据之间的时间差)也并没有上限1.5. MySQL复制是其内置的一把“瑞士军刀”1.6. MySQL的复制基本上是向后兼容的1.6.1. 新版本的服务器可以作为老版本的服务器的副本1.6.2. 老版本的服务器作为新版本的服务器的副本通常是不可行的1.7. 通过复制可以将读操作指向副本来获得更好的读扩展性1.7.1. 并不适合通过复制来扩展写操作1.8. 在一主库多副本库的架构中,写操作会被执行多次,这时候整个系统的性能取决于写入最慢的那部分1.9. 在复制架构中,读取和重放日志事件是解耦的1.9.1. 允许读取日志和重放日志异步进行1.9.2. I/O线程和SQL线程都是可以独立运行的2. 用途2.1. 数据分发2.1.1. 不会对带宽造成很大的压力2.1.2. 基于行的复制会比传统的基于语句的复制模式的带宽压力更大2.1.3. 如果为了保持很低的复制延迟,最好有一个稳定的、低延迟连接2.2. 读流量扩展2.2.1. 可以将读操作分布到多台服务器上,实现对读密集型应用的优化2.2.2. 对于小规模的应用,可以简单地对机器名做硬编码或使用DNS轮询2.3. 备份2.3.1. 一项有助于备份的有价值的技术,但副本不是备份,也不能够取代备份2.4. 分析与报告2.4.1. 为报告/分析(在线分析处理,OLAP)查询使用专用的副本是一项很好的策略2.4.2. 可以很好地隔离此类查询产生的压力,以避免对满足外部客户需求的在线业务产生影响2.5. 高可用性和故障切换2.5.1. 有助于避免MySQL成为应用程序中的单点故障2.5.2. 一个包含复制的设计良好的故障切换系统能够显著地缩短宕机时间2.6. MySQL升级测试2.6.1. 先使用一个更高版本的MySQL作为副本,确保查询能够在此副本上按照预期执行,再升级所有的实例3. 步骤3.1. 源端把数据更改记录到二进制日志中,称之为“二进制日志事件”(binary log events)3.2. 副本将源上的日志复制到自己的中继日志中3.3. 副本读取中继日志中的事件,将其重放到副本数据之上4. 原理4.1. 复制格式4.1.1. 基于语句的4.1.1.1. 通过记录所有在源端执行的数据变更语句来实现的4.1.1.2. 简单且紧凑4.1.1.3. 一条更新了大量数据的SQL语句,在二进制日志中可能仅仅需要几十字节存储4.1.1.4. “不确定性”的SQL语句问题4.1.1.4.1. 如果在源和副本上,记录的排序不同,这条SQL语句在源和副本上删除的100条记录就会不同,这将导致数据不一致4.1.1.5. 除非某些场景下明确需要临时使用基于语句的复制4.1.2. 基于行的4.1.2.1. 每条被改变的记录都会作为事件被写入二进制日志4.1.2.2. 让二进制日志的大小发生巨大的增长4.1.2.3. 建议坚持使用基于行的复制4.1.2.3.1. 提供了最安全的数据复制方法4.1.3. 混合模式4.1.3.1. the mixed method4.1.3.2. 事件的写入,默认使用基于语句的格式,仅在需要时才切换到基于行的格式4.1.3.3. 在写入每个事件时会有很多的判断条件,以确定使用哪种格式,而这也会导致二进制日志中出现不可预测的事件4.1.3.4. 不使用4.2. 全局事务标识符4.2.1. GTID4.2.2. 使用GTID,源服务器提交的每个事务都被分配一个唯一标识符4.2.3. 由server_uuid和一个递增的事务编号组成的4.2.4. 当事务被写入二进制日志时,GTID也随之被写入4.2.4.1. 当SQL线程提交事务时,它也会将GTID标记为执行完成4.2.5. GTID解决了运行MySQL复制的一个令人痛苦的问题:处理日志文件和位置4.2.6. 强烈建议在数据库中启用GTID4.3. 崩溃后的复制安全4.3.1. innodb_flush_log_at_trx_commit=14.3.1.1. 可以保障每个事务日志都被同步地写到磁盘4.3.1.2. 这是一个符合ACID要求的配置,将最大限度地保护你的数据4.3.1.3. 二进制日志事件首先被提交,然后事务将被提交并写入磁盘4.3.1.4. 此参数设置为1将增加磁盘写入操作的频次,同时确保数据的持久性4.3.2. sync_binlog=14.3.2.1. 控制MySQL将二进制日志数据同步到磁盘的频率4.3.2.2. 设置为1意味着在每次事务执行的时候都会把二进制日志同步写入磁盘4.3.2.3. 可以防止在服务器崩溃时丢失事务4.3.2.4. 会增加磁盘写入量4.3.3. relay_log_info_repository=TABLE4.3.3.1. 信息将被转移到MySQL本身的InnoDB表中,允许复制更新同一事务中的事务和中继日志信息4.3.3.2. 会在一个原子操作中完成,并有助于崩溃恢复4.3.4. relay_log_recovery=ON4.3.4.1. 使得副本服务器在检测到崩溃时会丢弃所有本地中继日志,并从源服务器中获取丢失的数据4.3.4.2. 确保了在崩溃中发生的磁盘上的任何损坏或不完整的中继日志都是可恢复的4.3.4.3. 不再需要配置sync_relay_log4.3.4.3.1. 因为在发生崩溃时,中继日志将被删除,也就无须花费额外的操作将它们同步到磁盘4.4. 延迟复制4.4.1. 某些副本有一些延迟反而是有好处的4.4.2. 可以让副本中的数据保持在线并且持续运行,但同时落后于源数据库数小时或者数天4.4.3. 配置语句是CHANGEREPLICATION SOURCE TO,配置选项为SOURCE_DELAY4.4.4. 场景4.4.4.1. 删除了一个表4.4.4.1.1. 从备份中恢复可能需要几个小时4.4.4.1.2. 如果使用了延迟复制的副本,则可以找到DROP TABLE语句对应的GTID,使副本服务器的复制运行到表被删除之前的时间点,这会大大减少修复时间4.5. 多线程复制4.5.1. 在副本端运行多个SQL线程,从而加快本地中继日志的应用4.5.2. 两种模式4.5.2.1. DATABASE模式4.5.2.1.1. 使用多线程更新不同的数据库4.5.2.1.2. 但不会有两个线程同时更新同一个数据库4.5.2.1.3. 将数据分布在MySQL的多个数据库中,则可以同时并且一致地更新它们,这种模式非常有效4.5.2.2. LOGICAL_CLOCK模式4.5.2.2.1. 允许对同一个数据库进行并行更新,只要它们都是同一个二进制日志组提交的一部分4.5.2.2.2. 人工延迟的配置参数4.5.2.2.2.1. binlog_group_commit_sync_delay(以微秒为单位的延迟)4.5.2.2.2.2. binlog_group_commit_sync_no_delay_count(决定中止等待之前要等待的事务数)4.5.2.2.2.3. 确保你的副本配置了参数replica_preserve_commit_order,这样就不会出现无序提交的问题4.6. 半同步复制4.6.1. 在启用半同步复制后,源在完成每个事务提交时,都需要确保事务至少被一个副本所接收4.6.2. 需要确认副本已收到并成功将其写入自己的中继日志(但不一定应用到本地数据)4.6.3. 如果在一定时间范围内没有副本确认事务,MySQL将恢复到标准的异步复制模式4.6.4. 半同步复制不是一种防止数据丢失的方法,而是可以让你拥有更具弹性的故障切换的更大工具集的一部分4.6.5. 建议不要依赖该功能来保证数据完整性4.7. 复制过滤器4.7.1. 可以让副本仅复制一部分数据4.7.2. 复制过滤器是一颗定时炸弹4.7.3. 从源上的二进制日志中过滤事件4.7.3.1. binlog_do_db4.7.3.2. binlog_ignore_db4.7.3.3. 不仅有可能破坏复制,还会使从备份中进行时间点恢复变得不可能4.7.3.3.1. 在大多数情况下都不应该使用它们4.7.4. 从副本上的中继日志中过滤事件4.7.4.1. replication_*选项在SQL线程从中继日志中读取事件时过滤事件