1 复制概述
Mysql内建的复制功能是构建大型,高性能应用程序的基础。将Mysql的数据分布到多个系统上去,这种分布的机制,是经过将Mysql的某一台主机的数据复制到其它主机(slaves)上,并从新执行一遍来实现的。复制过程当中一个服务器充当主服务器,而一个或多个其它服务器充当从服务器。主服务器将更新写入二进制日志文件,并维护文件的一个索引以跟踪日志循环。这些日志能够记录发送到从服务器的更新。当一个从服务器链接主服务器时,它通知主服务器从服务器在日志中读取的最后一次成功更新的位置。从服务器接收从那时起发生的任何更新,而后封锁并等待主服务器通知新的更新。mysql
请注意当你进行复制时,全部对复制中的表的更新必须在主服务器上进行。不然,你必需要当心,以免用户对主服务器上的表进行的更新与对从服务器上的表所进行的更新之间的冲突。sql
1.1 mysql支持的复制类型:
(1):基于语句的复制: 在主服务器上执行的SQL语句,在从服务器上执行一样的语句。MySQL默认采用基于语句的复制,效率比较高。
一旦发现无法精确复制时, 会自动选着基于行的复制。
(2):基于行的复制:把改变的内容复制过去,而不是把命令在从服务器上执行一遍. 从mysql5.0开始支持
(3):混合类型的复制: 默认采用基于语句的复制,一旦发现基于语句的没法精确的复制时,就会采用基于行的复制。数据库
1.2 . 复制解决的问题
MySQL复制技术有如下一些特色:
(1) 数据分布 (Data distribution )
(2) 负载平衡(load balancing)
(3) 备份(Backups)
(4) 高可用性和故障切换
(4) MySQL升级测试 使用一个更高版本的MySQL做为备库,保证在升级所有实例前,查询可以在备库按照预期执行。缓存
1.3 复制如何工做
总体上来讲,复制有3个步骤:服务器
(1) master将改变记录到二进制日志(binary log)中(这些记录叫作二进制日志事件,binary log events);网络
(2) slave将master的binary log events拷贝到它的中继日志(relay log);session
(3) slave重作中继日志中的事件,将改变反映它本身的数据。架构
下图描述了复制的过程:异步
该过程的第一部分就是master记录二进制日志。在每一个事务更新数据完成以前,master在二日志记录这些改变。MySQL将事务串行的写入二进制日志,即便事务中的语句都是交叉执行的。在事件写入二进制日志完成后,master通知存储引擎提交事务。
下一步就是slave将master的binary log拷贝到它本身的中继日志。首先,slave开始一个工做线程——I/O线程。I/O线程在master上打开一个普通的链接,而后开始binlog dump process。Binlog dump process从master的二进制日志中读取事件,若是已经跟上master,它会睡眠并等待master产生新的事件。I/O线程将这些事件写入中继日志。
SQL slave thread(SQL从线程)处理该过程的最后一步。SQL线程从中继日志读取事件,并重放其中的事件而更新slave的数据,使其与master中的数据一致。只要该线程与I/O线程保持一致,中继日志一般会位于OS的缓存中,因此中继日志的开销很小。
此外,在master中也有一个工做线程:和其它MySQL的链接同样,slave在master中打开一个链接也会使得master开始一个线程。复制过程有一个很重要的限制——复制在slave上是串行化的,也就是说master上的并行更新操做不能在slave上并行操做。函数
2 、复制配置
因为场景不一样,基本的步骤仍是有差别的,最基本的场景是新安装的主库和备库,总的来讲分为如下几步:
1.在每台服务器上建立复制帐号。
2.配置主库和备库。
3.通知备库链接到主库并从主库复制数据。
2.一、建立复制帐号
MySQL会赋予一些特殊权限给复制线程。在备库运行的I/O线程会创建一个到主库的TCP/IP链接,这意味着必须在主库建立一个用户,并赋予去合适的权限。备库I/O线程以该用户名链接到主库并读取其二进制日志。经过以下语句建立用户帐号:
主库和备库都建立该帐号。
2.二、配置主库和备库
主库打开二进制日志并指定一个独一无二的服务器,在主库my.cnf文件中增长火修改以下内容:
log_bin = mysql-bin
server_id =10
若是以前没有在MySQL的配置文件中指定log-bin选项,就须要从新启动MySQL。为肯定二进制日志文件是否已经在主库上建立,使用SHOW MASTER STATUS命令,检查输出是否与以下的一致。MySQL会为文件名增长一些数字,因此这里看到的文件名和你定义的会有点不同。、
2.三、启动复制
开始复制的基本命令
SHOW SLAVE STATUS语句来检查复制是否正确执行。
2.4从另外一个服务器开始复制
有几种方法来初始化备库或者从其余服务器克隆数据到备库。包括从主库复制数据、从另一台备库克隆数据,以及使用最近的一次备份来启动备库,须要有三个条件来让主库和备库保持同步:
下面是从别的服务器克隆备库的方法:
使用冷备份
最基本的方法是关闭主库,把数据复制到备库。重启主库后,会使用一个新的二进制日志文件,咱们在备库经过执行CHANGE MASTER TO指向这个文件的起始处。
使用热备份
若是仅使用了MyISAM表,能够在主库运行时使用mysqlhotcopy货rsync来复制数据。
使用mysqldump
若是只包含InnoDB表,那么可使用一下命令来转储主库数据并将其加载到备库
使用快照或备份
使用另外的备库
三、复制的原理
已经讨论了关于复制的一些基本东西,下面深刻讨论一下复制。
3.一、基于语句的复制(Statement-Based Replication)
MySQL 5.0及以前的版本仅支持基于语句的复制(也叫作逻辑复制,logical replication),这在数据库并不常见。master记录下改变数据的查询,而后,slave从中继日志中读取事件,并执行它,这些SQL语句与master执行的语句同样。
这种方式的优势就是实现简单。此外,基于语句的复制的二进制日志能够很好的进行压缩,并且日志的数据量也较小,占用带宽少——例如,一个更新GB的数据的查询仅须要几十个字节的二进制日志。而mysqlbinlog对于基于语句的日志处理十分方便。
可是,基于语句的复制并非像它看起来那么简单,由于一些查询语句依赖于master的特定条件,例如,master与slave可能有不一样的时间。因此,MySQL的二进制日志的格式不只仅是查询语句,还包括一些元数据信息,例如,当前的时间戳。即便如此,仍是有一些语句,好比,CURRENT USER函数,不能正确的进行复制。此外,存储过程和触发器也是一个问题。
另一个问题就是基于语句的复制必须是串行化的。这要求大量特殊的代码,配置,例如InnoDB的next-key锁等。并非全部的存储引擎都支持基于语句的复制。
3.二、基于行的复制(Row-Based Replication)
MySQL增长基于记录的复制,在二进制日志中记录下实际数据的改变,这与其它一些DBMS的实现方式相似。这种方式有优势,也有缺点。优势就是能够对任何语句都能正确工做,一些语句的效率更高。主要的缺点就是二进制日志可能会很大,并且不直观,因此,你不能使用mysqlbinlog来查看二进制日志。
对于一些语句,基于记录的复制可以更有效的工做,如:
mysql> INSERT INTO summary_table(col1, col2, sum_col3)
-> SELECT col1, col2, sum(col3)
-> FROM enormous_table
-> GROUP BY col1, col2;
假设,只有三种惟一的col1和col2的组合,可是,该查询会扫描原表的许多行,却仅返回三条记录。此时,基于记录的复制效率更高。
另外一方面,下面的语句,基于语句的复制更有效:
mysql> UPDATE enormous_table SET col1 = 0;
此时使用基于记录的复制代价会很是高。因为两种方式不能对全部状况都能很好的处理,因此,MySQL 5.1支持在基于语句的复制和基于记录的复制以前动态交换。你能够经过设置session变量binlog_format来进行控制。
3.三、复制相关的文件
除了二进制日志和中继日志文件外,还有其它一些与复制相关的文件。以下:
(1)mysql-bin.index
服务器一旦开启二进制日志,会产生一个与二日志文件同名,可是以.index结尾的文件。它用于跟踪磁盘上存在哪些二进制日志文件。MySQL用它来定位二进制日志文件。它的内容以下(个人机器上):
(2)mysql-relay-bin.index
该文件的功能与mysql-bin.index相似,可是它是针对中继日志,而不是二进制日志。内容以下:
.\mysql-02-relay-bin.000017
.\mysql-02-relay-bin.000018
(3)master.info
保存master的相关信息。不要删除它,不然,slave重启后不能链接master。内容以下(个人机器上):
I/O线程更新master.info文件,内容以下(个人机器上):
.\mysql-02-relay-bin.000019
254
mysql-01-bin.000010
286
0
52813
(4)relay-log.info
包含slave中当前二进制日志和中继日志的信息。
3.四、发送复制事件到其它备库
当设置log_slave_updates时,你可让slave扮演其它slave的master。此时,slave把SQL线程执行的事件写进行本身的二进制日志(binary log),而后,它的slave能够获取这些事件并执行它。以下:
3.五、复制过滤(Replication Filters)
复制过滤可让你只复制服务器中的一部分数据,有两种复制过滤:在master上过滤二进制日志中的事件;在slave上过滤中继日志中的事件。以下:
四、复制的经常使用拓扑结构
复制的体系结构有如下一些基本原则:
(1) 每一个slave只能有一个master;
(2) 每一个slave只能有一个惟一的服务器ID;
(3) 每一个master能够有不少slave;
(4) 若是你设置log_slave_updates,slave能够是其它slave的master,从而扩散master的更新。
MySQL不支持多主服务器复制(Multimaster Replication)——即一个slave能够有多个master。可是,经过一些简单的组合,咱们却能够创建灵活而强大的复制体系结构。
4.一、单一master和多slave
由一个master和一个slave组成复制系统是最简单的状况。Slave之间并不相互通讯,只能与master进行通讯。
在实际应用场景中,MySQL复制90%以上都是一个Master复制到一个或者多个Slave的架构模式,主要用于读压力比较大的应用的数据库端廉价扩展解决方案。由于只要Master和Slave的压力不是太大(尤为是Slave端压力)的话,异步复制的延时通常都不多不多。尤为是自从Slave端的复制方式改为两个线程处理以后,更是减少了Slave端的延时问题。而带来的效益是,对于数据实时性要求不是特别Critical的应用,只须要经过廉价的pcserver来扩展Slave的数量,将读压力分散到多台Slave的机器上面,便可经过分散单台数据库服务器的读压力来解决数据库端的读性能瓶颈,毕竟在大多数数据库应用系统中的读压力仍是要比写压力大不少。这在很大程度上解决了目前不少中小型网站的数据库压力瓶颈问题,甚至有些大型网站也在使用相似方案解决数据库瓶颈。
以下:
若是写操做较少,而读操做很时,能够采起这种结构。你能够将读操做分布到其它的slave,从而减少master的压力。可是,当slave增长到必定数量时,slave对master的负载以及网络带宽都会成为一个严重的问题。
这种结构虽然简单,可是,它却很是灵活,足够知足大多数应用需求。一些建议:
(1) 不一样的slave扮演不一样的做用(例如使用不一样的索引,或者不一样的存储引擎);
(2) 用一个slave做为备用master,只进行复制;
(3) 用一个远程的slave,用于灾难恢复;
你们应该都比较清楚,从一个Master节点能够复制出多个Slave节点,可能有人会想,那一个Slave节点是否能够从多个Master节点上面进行复制呢?至少在目前来看,MySQL是作不到的,之后是否会支持就不清楚了。
MySQL不支持一个Slave节点从多个Master节点来进行复制的架构,主要是为了不冲突的问题,防止多个数据源之间的数据出现冲突,而形成最后数据的不一致性。不过据说已经有人开发了相关的patch,让MySQL支持一个Slave节点从多个Master结点做为数据源来进行复制,这也正是MySQL开源的性质所带来的好处。
4.二、主动模式的Master-Master(Master-Master in Active-Active Mode)
Master-Master复制的两台服务器,既是master,又是另外一台服务器的slave。这样,任何一方所作的变动,都会经过复制应用到另一方的数据库中。
可能有些读者朋友会有一个担忧,这样搭建复制环境以后,难道不会形成两台MySQL之间的循环复制么?实际上MySQL本身早就想到了这一点,因此在MySQL的BinaryLog中记录了当前MySQL的server-id,并且这个参数也是咱们搭建MySQLReplication的时候必须明确指定,并且Master和Slave的server-id参数值比须要不一致才能使MySQLReplication搭建成功。一旦有了server-id的值以后,MySQL就很容易判断某个变动是从哪个MySQLServer最初产生的,因此就很容易避免出现循环复制的状况。并且,若是咱们不打开记录Slave的BinaryLog的选项(--log-slave-update)的时候,MySQL根本就不会记录复制过程当中的变动到BinaryLog中,就更不用担忧可能会出现循环复制的情形了。
如图:
主动的Master-Master复制有一些特殊的用处。例如,地理上分布的两个部分都须要本身的可写的数据副本。这种结构最大的问题就是更新冲突。假设一个表只有一行(一列)的数据,其值为1,若是两个服务器分别同时执行以下语句:
在第一个服务器上执行:
mysql> UPDATE tbl SET col=col + 1;
在第二个服务器上执行:
mysql> UPDATE tbl SET col=col * 2;
那么结果是多少呢?一台服务器是4,另外一个服务器是3,可是,这并不会产生错误。
实际上,MySQL并不支持其它一些DBMS支持的多主服务器复制(Multimaster Replication),这是MySQL的复制功能很大的一个限制(多主服务器的难点在于解决更新冲突),可是,若是你实在有这种需求,你能够采用MySQL Cluster,以及将Cluster和Replication结合起来,能够创建强大的高性能的数据库平台。可是,能够经过其它一些方式来模拟这种多主服务器的复制。
4.三、主动-被动模式的Master-Master(Master-Master in Active-Passive Mode)
这是master-master结构变化而来的,它避免了M-M的缺点,实际上,这是一种具备容错和高可用性的系统。它的不一样点在于其中一个服务只能进行只读操做。如图:
4.4 级联复制架构 Master –Slaves - Slaves
在有些应用场景中,可能读写压力差异比较大,读压力特别的大,一个Master可能须要上10台甚至更多的Slave才可以支撑注读的压力。这时候,Master就会比较吃力了,由于仅仅连上来的SlaveIO线程就比较多了,这样写的压力稍微大一点的时候,Master端由于复制就会消耗较多的资源,很容易形成复制的延时。
遇到这种状况如何解决呢?这时候咱们就能够利用MySQL能够在Slave端记录复制所产生变动的BinaryLog信息的功能,也就是打开—log-slave-update选项。而后,经过二级(或者是更多级别)复制来减小Master端由于复制所带来的压力。也就是说,咱们首先经过少数几台MySQL从Master来进行复制,这几台机器咱们姑且称之为第一级Slave集群,而后其余的Slave再从第一级Slave集群来进行复制。从第一级Slave进行复制的Slave,我称之为第二级Slave集群。若是有须要,咱们能够继续往下增长更多层次的复制。这样,咱们很容易就控制了每一台MySQL上面所附属Slave的数量。这种架构我称之为Master-Slaves-Slaves架构
这种多层级联复制的架构,很容易就解决了Master端由于附属Slave太多而成为瓶颈的风险。下图展现了多层级联复制的Replication架构。
固然,若是条件容许,我更倾向于建议你们经过拆分红多个Replication集群来解决
上述瓶颈问题。毕竟Slave并无减小写的量,全部Slave实际上仍然仍是应用了全部的数据变动操做,没有减小任何写IO。相反,Slave越多,整个集群的写IO总量也就会越多,咱们没有很是明显的感受,仅仅只是由于分散到了多台机器上面,因此不是很容易表现出来。
此外,增长复制的级联层次,同一个变动传到最底层的Slave所须要通过的MySQL也会更多,一样可能形成延时较长的风险。
而若是咱们经过分拆集群的方式来解决的话,可能就会要好不少了,固然,分拆集群也须要更复杂的技术和更复杂的应用系统架构。
4.五、带从服务器的Master-Master结构(Master-Master with Slaves)
这种结构的优势就是提供了冗余。在地理上分布的复制结构,它不存在单一节点故障问题,并且还能够将读密集型的请求放到slave上。
级联复制在必定程度上面确实解决了Master由于所附属的Slave过多而成为瓶颈的问题,可是他并不能解决人工维护和出现异常须要切换后可能存在从新搭建Replication的问题。这样就很天然的引伸出了DualMaster与级联复制结合的Replication架构,我称之为Master-Master-Slaves架构
和Master-Slaves-Slaves架构相比,区别仅仅只是将第一级Slave集群换成了一台单独的Master,做为备用Master,而后再从这个备用的Master进行复制到一个Slave集群。
这种DualMaster与级联复制结合的架构,最大的好处就是既能够避免主Master的写入操做不会受到Slave集群的复制所带来的影响,同时主Master须要切换的时候也基本上不会出现重搭Replication的状况。可是,这个架构也有一个弊端,那就是备用的Master有可能成为瓶颈,由于若是后面的Slave集群比较大的话,备用Master可能会由于过多的SlaveIO线程请求而成为瓶颈。固然,该备用Master不提供任何的读服务的时候,瓶颈出现的可能性并非特别高,若是出现瓶颈,也能够在备用Master后面再次进行级联复制,架设多层Slave集群。固然,级联复制的级别越多,Slave集群可能出现的数据延时也会更为明显,因此考虑使用多层级联复制以前,也须要评估数据延时对应用系统的影响。