1、复制的意义html
mysql的复制功能是构建基于MySql大规模,高性能应用的基础,咱们能够经过为服务器配置一个或多个备库来进行数据同步;复制功能不只有利于构建高性能的应用,同时也是高可用性,可扩展行,灾难恢复,备份以及数据仓库等工做的基础mysql
2、复制的方式sql
Mysql支持3种方式:基于语句的复制、基于行的复制、混合复制。对应的binlog的格式也有三种:STATEMENT,ROW,MIXED数据库
(1)基于语句的复制(SBR)缓存
每一条会修改数据的sql语句会记录到binlog中。优势是不须要记录每一条sql语句和每一行的数据变化,减小了binlog日志量,节约IO,提升性能。缺点是在某些状况下会致使master-slave中的数据不一致(如RAND(),UUID(),存储过程,触发器等)服务器
(2)基于行的复制(RBR)多线程
不记录每条sql语句的上下文信息,转而需记录哪条数据被修改了,修改为什么样了。而且不会出现某些特定状况下的存储过程、触发器等在基于语句复制的模式下致使没法被正确复制的问题。缺点是会产生大量的日志,尤为是alter table的时候会让日志暴涨,没法准确的判断执行了那些sql,此外在备库上改表的schema时会出现复制失败,好比没有在最后加列或删除列架构
(3)混合复制(MRB)并发
以上两种模式的混合使用,MySQL会根据执行的SQL语句选择日志保存方式,通常的复制使用STATEMENT模式保存binlog,对于STATEMENT模式没法复制的操做使用ROW模式保存binlog。oracle
3、与复制相关的文件
mysql-bin.index:在服务器上开启二进制日志的同时会生成一个和二进制日志同名的但以.index做为后缀的文件,该文件用于记录磁盘上的二进制日志文件,这里的“index”并非指表的索引,而是说这个文件的每一行包含了一个二进制的文件名,Mysql依赖于这个文件,除非在这个文件里有记录不然mysql识别不了二进制文件
mysql-relay-bin-index:中继日志的索引文件和mysql-bin.index的做用相似
master.info:这个文件用于保存备库连接到主库所须要的信息,格式为存文本,不一样的mysql版本,其记录的信息也可能不一样;此文件不能删除,不然备库在重启后没法链接到主库。此外这个文件以文本的形式记录了复制用户的密码,因此要注意对此文件的权限控制
relay-log.info:这个文件包含了当前备库负责的二进制日志和中继日志坐标(例如,备库复制在主库复制的位置),一样也不用删除这个文件,不然备库在重启后将没法获知从哪一个位置开始复制,可能致使重放已经执行的语句
4、复制的原理
一、主库把数据更改记录在二进制日志中(Binary Log)中(这些记录被称为二进制日志事件)
二、备库启动一个工做进程,称为I/O线程,经过I/O线程向主库创建一个普通的客户端链接,备库还会启动一个SQL线程
三、在主库上启动一个特殊的二进制转储(binlog dump)线程(该线程没有对应的SQL命令)
四、主库上的二进制转储线程会读取主库上的二进制日志中的事件经过socket链接发送给从库,备库上的I/O线程会将接收到的事件记录到中继日志中;主库上的二进制转储线程不会对事件进行轮询,若是该进程追遇上了主库,它将进入睡眠状态,直到主库发送信号量通知其有新的事件产生时才会被唤醒
五、备库的SQL线程执行最后一步,该线程从中继日志中读取事件并在备库中执行,从而实现备库数据的更新。当SQL线程追遇上I/O线程时,中继日志一般已经在系统缓存中,因此中继日志的开销很低。SQL线程执行的事件也能够经过配置选项来决定是否写入备库的二进制日志中
5、复制的场景
一、同步复制场景
MySQL Cluster(NDB)采用同步复制,保证集群内数据的强一致性。
其基于shared-nothing架构的内存存储引擎,应用场景有限,业务不多采用。
二、异步复制场景
数据写入主库即返回,从库经过IO线程拉取日志,再经过SQL线程进行异步回放。
优势:写入主库便可,无数据复制代价
缺点:业务数据读取不一致;主库crash时,从库数据和主库不一致
应用场景:对数据读取一致性要求不高的业务
三、半同步复制场景
1) 半同步
MySQL 5.5引入了半同步复制(semisync),保证至少有一个slave与master一致。
http://dev.mysql.com/doc/refman/5.6/en/replication-semisync.html
master把数据写入后,将binlog发给slave,半同步复制不要求slave执行,slave收到日志后就发送ack便可,master收到第一个ack后,事务才算结束。
但这种方式可能会形成主从数据不一致:当master innodb commit执行成功,再把binlog同步给slave以前crash,就会形成数据不一致。
2) 分组半同步
采用半同步复制,同机房的从库大几率首先返回ack,这样跨机房容灾成为空谈。因而发展出了分组半同步(semisync + group slave),将不一样机房划分为不一样的group,每一个机房(group)至少有一个从库返回ack,事务才算完成。
优势:半同步和分组半同步最大限度的保证了数据一致性
缺点:
引入同步(等待ack)形成的性能问题
单机房故障会hang住事务,须要退化为异步
数据仍然存在不一致可能
主库在commit和binlog同步之间crash
半同步在超时后会退化为异步(默认10000ms)
3) 无损半同步
因为MySQL 5.5,5.6版本的半同步存在数据不一致问题(先commit后同步),MySQL 5.7.2引入了无损(loessness)半同步,即数据写完slave的relay log后再commit。
https://dev.mysql.com/doc/refman/5.7/en/replication-semisync.html
http://my-replication-life.blogspot.com/2013/09/loss-less-semi-synchronous-replication.html
6、并行复制的方式
一、基于库级别的并行复制
mysql5.6版本
io_thread:根据binlog dump协议从主库拉取binlog, 并将binlog转存到本地的relaylog;
Coordinator_thread:负责读取relay log,将读取的binlog event以事务为单位分发到各个worker thread进行执行;在必要时本身执行binlog event
worker_thread(sql_thread):执行分配到的binlog event,各个线程之间互不影响
多线程原理:
sql_thread的分发是依据当前事务锁操做的数据库名称来进行分发,若是事务是跨分片的,须要等待已分配的改数据库的事务所有执行完毕,才会继续分发
二、基于GroupCommit的并行复制
mysql5.7版本,并行复制的实现添加了另一种并行的方式,即主库在orderd_commit中的第二阶段的时候,将同一批commit的binlog打上一个相同的seqno标签,同一时间戳的事务在备库是能够同时执行的,所以简化了并行复制的逻辑,并打破了mysql5.6版本相同Db不能并行复制的限制。备库在执行时,具备同一seqno的事务在备库能够并发的执行,互补干扰,也不须要绑定信息,后一批seqno的事务须要等待前一批seqno的事务执行完后才能够执行
优势:对SRB和RBR都支持
缺点:事务越大,DML操做越多,主库上能同时提交的概率越小,从库上回复的并行度也就越小
业务正常压力模式下,主库同时提交的事务并很少,历史备份或者从库schema change后在追若干前的数据所须要的时间没法显著的缩短
三、基于表级别的并行复制
将原有mysql5.6的基于Db基本的分发改为db_name+table_name,不一样db_name+table_name的能够分发给不一样的worker_thread进行执行
四、基于行级别的并行复制
基于Mysql Row格式的binlog记录了每一行的全部字段信息,所以能够在从中取出每一行的primary key或者unique key,经过db_name+table_name+primary_key来进行冲突检查,对于不冲突的事务能够并行执行,达到行级别的并行复制缺点:只支持RBR
7、其余知识点
一、server id
server_id定义在my.cnf中 server_id = xxx,必须明确指定一个惟一的服务器ID,默认的服务器ID一般为1(这和版本相关,一些mysql版本根本不容许使用这个值)。使用默认值可能会致使和其余服务器的ID冲突,所以要保证它是惟一且不变的
Mysql在复制过程当中为了防止环形无限复制,当SQL线程读取中继日志的时候,会丢去事件中记录的服务器ID和该服务器自己ID相同的事件,从而打破复制过程当中的无限循环。在某些复制拓扑结构下打破无限循环很是重要,例如主-主复制结构
二、redo log 和 bin log
与oracle 不一样,mysql 的主库与备库的同步是经过 binlog 实现的,而redo日志只作为mysql 实例的crash recovery使用。
mysql在4.x 的时候放弃redo 的同步策略而引入 binlog的同步,一个重要缘由是为了兼容其它非事务存储引擎,不然主备同步是没有办法进行的。
redo 日志同步属于物理同步方法,简单直接,将修改的物理部分传送到备库执行,主备共用一致的 LSN,只要保证 LSN 相同便可,同一时刻,只能主库或备库一方接受写请求; binlog的同步方法属于逻辑复制,分为statement 或 row 模式,其中statement记录的是SQL语句,Row 模式记录的是修改以前的记录与修改以后的记录,即前镜像与后镜像;备库经过binlog dump 协议拉取binlog,而后在备库执行。若是拉取的binlog是SQL语句,备库会走和主库相同的逻辑,若是是row 格式,则会调用存储引擎来执行相应的修改。