MySQL主从复制
引用:1、http://www.cnblogs.com/boothsun/p/7872669.html
2、https://www.cnblogs.com/gl-developer/p/6170423.html
3、https://www.cnblogs.com/kylinlin/p/5258719.html
MySQL主从复制是MySQL“水平扩展”架构的一种,主从复制可以使数据从一个数据库服务器复制到多个其他服务器上,多个数据备份可实现高可用、高扩展、容灾恢复等,通过读写分离还能提高数据库的负载性能。
下图就描述了一个多个数据库间主从复制与读写分离的模型(来源网络):
在一主多从的数据库体系中,多个从服务器采用异步的方式更新主数据库的变化,业务服务器在执行写或者相关修改数据库的操作是在主服务器上进行的,读操作则是在各从服务器上进行。
Mysql主从复制的实现原理图大致如下(来源网络):
从上图,我们可以知道,MySQL复制主要有三个步骤:
- 在主库上把数据更改记录到二级制日志(binary Log)中(二进制日志事件)。
- 从库将主库上的日志复制到自己的中继日志(Relay Log)中。
- 从库读取中继日志中的事件,将其重放到从库数据之上。
细说:
第一步是在主库上记录二进制日志。在每次MySQL准备提交事务完成数据更新前,主库将数据更新的事件记录到二进制日志中。MySQL会按事务提交的顺序而非每条语句的执行顺序来记录二进制日志。在记录二进制日志后,主库会告诉存储引擎可以提交事务了。
第二步,从库会启动一个工作线程,称为I/O线程,I/O线程跟主库建立一个普通的客户端连接,然后在主库上启动一个特殊的二进制转储(binlog dump)线程,这个二进制转储线程会读取主库上二进制日志中的事件。它不会对事件进行轮询。如果该线程追赶上主库,它将进入休眠状态,直到主库发送信号量通知其有新的事件产生时才会被唤醒,从库I/O线程会将接收到的事件记录到中继日志中。
第三步,从库SQL线程执行最后一步,该线程从中继日志中读取事件并在从库执行,从而实现从库数据的更新。当SQL线程追赶上I/O线程时,中继日志通常已经全部在系统缓存中,所以中继日志的开销很低。SQL线程执行的事件也可以通过配置选项来决定是否写入其自己的二进制日志中。
这种架构实现了获取事件和重放事件的解耦,但是也限制了整个复制过程只能串行化执行,因为只有一个SQL线程来重放中继日志中的事件。
总而言之:
- MySQL复制功能可以实现MySQL的“水平扩展”。
- 所谓复制简单来说 就是让一台服务器的数据变更同步到其他服务器。
- 现有MySQL主从复制方式都是通过在主库上记录binlog,在从库上重放的方式来实现的。
- 主从间数据同步可以有助于MySQL的高可用、灾后数据恢复、数据仓库等工作。
- 异步复制的方式,会导致在某个时间点上产生主从数据不一致性。(从库缺失数据)
数据库复制所能解决的问题
- 数据分布:异地数据存储。
- 负载均衡:读写分离,多台从库之间可以通过硬编码或使用DNS轮询(将一个机器名指向多个IP地址)再或者Linux虚拟服务器(Linux Virtual Server , LVS)实现负载均衡。
- 备份: 数据备份。
- 高可用性和故障切换:避免单点故障,故障切换。
- MySQL升级测试:这种做法比较普遍,使用一个更高版本的MySQL作为备库,保证升级全部实例前,查询能够在备库按照预期执行。
MySQL复制方式
1、异步复制
主库执行完直接返回给客户端,主库宕机,数据不一致
2、同步复制
从库执行完,主库再返回给客户端,严重影响性能
3、半同步复制
至少有一个从库接收到并写到relay log中返回给主库ACK
4、延迟复制
在异步复制基础上设置延迟时间
MySQL复制格式
1、Statement,基于SQL语句的复制
主服务器会把影响数据变更的SQL语句写入到日志中,然后从服务器会执行该日志。
优:简单、方便审计、日志文件更小(更新好几兆数据的语句在二进制日志里可能只占几十个字节)
缺:数据可能不一致(当前的时间戳)、更新必须是串行化,需要更多的锁
2、raw,基于行的复制
将实际增删改数据记录在二进制日志中。
优:可以正确地复制每一行
缺:日志会很大(变更的每一行数据都会被记录到二进制日志)
3、混合型复制
默认情况下使用的是基于语句的复制方式,但如果发现语句无法被正确地复制,就切换到基于行的复制模式。
面试题
1、主从复制数据不一致的原因?
- 主库binlog格式为statement,同步到从库执行后可能造成主从不一致;
- 主库执行更改前有设置执行set sql_log_bin=0,这样主库不记录binlog,从库也就没这些数据;
- 从库未设置只读,可能误写入
- 主库或从库宕机,使binlog或relay log出现损坏
- 主从实例版本不一致,主高从低,从库有可能不支持
2、如何避免主从不一致?
- 主库binlog格式设为raw;
- 主库不可执行set sql_log_bin=0;
- 从库设置只读;
- 定期主从一致性检查;
- 主从实例版本保持一致;