MySQL数据库复制概论

每当咱们讨论一项(新的)领域技术的时候,最好的方式一般是首先抛出一些问题,这些问题大体分为三类:诶?这项技术又是什么玩意(What)?这项技术为何会存在?咱们已经有那么多解决方案(Method)了,咱们问什么要用它(Why)?若是这项技术那么好且咱们正好有场景能够用到这项技术,且能使咱们的系统获得很乐观的优化,那么咱们怎么用呢(How)?大概已经有同窗以为这些问题很熟悉了,是的,这就是黄金全法则提出的三个问题,对于每种新鲜事物咱们首先基于这三个问题去了解,更有利于弄清楚事情的本质,端正态度去了解,而不是由于新,由于你们都说好,才要去了解……。说了那么多前奏,咱们能够开始了,今天咱们就带着黄金圈法则提出的三个问题去看看MySQL数据库复制这项领域技术,而后再结合实际应用扩展一些问题,本文也仅仅是结合本身了解的皮毛以抛砖引玉的态度和你们一块儿分享。sql


WHAT?数据库

MySQL复制使得一台Mysql数据库服务器的数据被拷贝到其余一台或者多台数据库服务器,前者一般被叫作Master,后者一般被叫作Slave。服务器

MySQL复制示意图网络

复制的结果是集群(Cluster)中的全部数据库服务器获得的数据理论上都是同样的,都是同一份数据,只是有多个copy。MySQL默认内建的复制策略是异步的,基于不一样的配置,Slave不必定要一直和Master保持链接不断的复制或等待复制,咱们指定复制全部的数据库,一部分数据库,甚至是某个数据库的某部分的表。并发

MySQL复制支持多种不一样的复制策略,包括同步、半同步、异步和延迟策略等。异步

  1. 同步策略:Master要等待全部Slave应答以后才会提交(MySql对DB操做的提交一般是先对操做事件进行二进制日志文件写入而后再进行提交)。
    ide

  2. 半同步策略:Master等待至少一个Slave应答就能够提交。性能

  3. 异步策略:Master不须要等待Slave应答就能够提交。优化

  4. 延迟策略:Slave要至少落后Master指定的时间。
    spa

MySQL复制同时支持多种不一样的复制模式:

  1. 基于语句的复制,Statement Based Replication(SBR)。

  2. 基于行的复制Row Based Replication(RBR)。

  3. 混合复制(Mixed)。


WHY?

这个问题其实也就是MySQL复制有什么好处,咱们能够将复制的好处归结于下面几类:

  1. 性能方面:MySQL复制是一种Scale-out方案,也即“水平扩展”,将原来的单点负载扩散到多台Slave机器中去,从而提升整体的服务性能。在这种方式下,全部的写操做,固然包括UPDATE操做,都要发生在Master服务器上。读操做发生在一台或者多台Slave机器上。这种模型能够在必定程度上提升整体的服务性能,Master服务器专一于写和更新操做,Slave服务器专一于读操做,咱们同时能够经过增长Slave服务器的数量来提升读服务的性能。

  2. 防腐化:因为数据被复制到了Slave,Slave能够暂停复制进程,进行数据备份,所以能够防止数据腐化。

  3. 故障恢复:同时多台Slave若是有一台Slave挂掉以后咱们还能够从其余Slave读取,若是配置了主从切换的话,当Master挂掉以后咱们还能够选择一台Slave做为Master继续提供写服务,这大大增长了应用的可靠性。

  4. 数据分析:实时数据能够存储在Master,而数据分析能够从Slave读取,这样不会影响Master的性能。


HOW?

这里咱们只介绍一下MySQL的复制是如何工做的,至于配置,网上也有不少相关的介绍,读者具体应用的时候能够再去查阅。咱们拿最经常使用的基于二进制文件的复制来看看。

MySQL复制工做示意图

MySQL的复制过程大概以下:

首先,主库在每次准备提交事务完成数据更新操做以前都会将数据更改操做记录到二进制日志中,这些日志是以二进制的方式记录数据更改的事件。值得一提的是二进制日志中记录的顺序其实是事务的提交顺序,而非SQL执行语句的顺序。在记录二进制日志以后,主库会告诉存储引擎事务能够提交了。

而后,备库会启动一个IO线程,之因此叫作IO线程是由于这个线程专门作IO相关的工做,包括和主库创建链接,而后在主库上启动一个特殊的二进制转储线程,这个转储线程会不断的读取二进制日志中的事件,发送给备库的IO线程,备库的IO线程会将事件记录到中继日志中。

备库会有一个叫作SQL的线程被开启,这个线程作的事情是读取中继日志中的DB操做事件在备库执行,从而实现数据更新。

总的来讲,在发生复制的主库服务器和备库服务器中,一共有三个线程在工做。


上面咱们已经大概了解的什么是复制?为何要复制?如何复制?这三个问题了,接下来咱们基于上面的介绍,提出一些实际应用可能会发生的问题来思考如何解决。博主自问自答的方式-。-


问答环节

问题一:经过复制模型虽然读能力能够经过扩展slave机器来达到提升,而写能力却不能,若是写达到瓶颈咱们应该怎么作呢?

答:咱们首先会得出结论,这种复制模型对于写少读多型应用是很是有优点的,其次,当遇到这种问题的时候咱们能够对数据库进行分库操做,所谓分库,就是将业务相关性比较大的表放在同一个数据库中,例如以前数据库有A,B,C,D四张表,A表和B表关系比较大,而C表和D表关系比较大,这样咱们把C表和D表分离出去成为一个单独的数据库,经过这种方式,咱们能够将原有的单点写变成双点写或多点些,从而下降原有主库的写负载。


问题二:由于复制是有延迟的,确定会发生主库写了,可是从库尚未读到的状况,遇到这种问题怎么办?

答:MySQL支持不一样的复制策略,基于不一样的复制策略达到的效果也是不同的,若是是异步复制,MySQL不能保证从库立马可以读到主库实时写入的数据,这个时候咱们要权衡选择不一样复制策略的利弊来进行取舍。所谓利弊,就是咱们是否对从库的读有那么高的实时性要求,若是真的有,咱们能够考虑使用同步复制策略,可是这种策略相比于异步复制策略会大大下降主库的响应时间和性能。咱们是否能够在应用的设计层面去避开这个问题?


问题三:复制的不一样模式有什么优缺点?咱们如何选择?

答:基于语句的复制其实是把主库上执行的SQL在从库上从新执行一遍,这么作的好处是实现起来简单,当前也有缺点,好比咱们SQL里面使用了NOW(),当同一条SQL在从库中执行的时候显然和在主库中执行的结果是不同的,注入此类问题能够类推。其次问题就是这种复制必须是串行的,为了保证串行执行,就须要更多的锁。

基于行的复制的时候二进制日志中记录的其实是数据自己,这样从库能够获得正确的数据,这种方式缺点很明显,数据必需要存储在二进制日志文件中,这无疑增长的二进制日志文件的大小,同时增长的IO线程的负载和网络带宽消耗。而相比于基于语句的复制还有一个优势就是基于行的复制无需重放查询,省去了不少性能消耗。

不管哪一种复制模式都不是完美的,日志如何选择,这个问题能够在理解他们的优缺点以后进行权衡。


问题四:复制的工做过程只有三个线程来完成,对于Master来讲,写是并发的,也就出现了一个IO线程要把全部并发的数据变动事件记录,这个IO线程会不会累死?当一个Master对应多个Slave的时候,其实在Master中会唤起多个IO线程,这无疑会增长Master的资源开销,若是出现事件堆积,也就是事件太多,来不及及时发送出去怎么办?另外就是Slave那边的IO线程和SQL线程也会有对应主库并发数据变动事件,而Slave方单个线程处理的问题,这个时候Slave线程会不会累死?

答:上面的问题确实会发生,上面第一个问题和第二个问题实际上是写负载的问题,当事件堆积太多,从库时延就会变大,Slave单SQL线程问题听说有参数能够开启并行操做,这个你们能够确认一下。


问题五:针对复制工做过程可能会出现的问题,主库写完二进制日志文件同时都会保存二进制日志的偏移量,可是当断电的时候,二进制日志文件没有刷新到磁盘,主库从新启动以后,从库尝试读该偏移量的二进制日志,会出现读不到的状况,这个问题应该怎么解决?

答:首先若是开启了sync_binlog选项,对于innodb同时设置innodb_flush_log_at_trx_commot=1,则能够保证二进制日志文件会被写入磁盘,但MyISAM引擎可能会致使数据损坏。若是没有开启这个选项,则能够经过制定从库的二进制偏移量为下一个二进制日志文件的开头,可是不能解决事件丢失问题。


问题六:从库在非计划的关闭或重启时,回去读master.info文件去找上次中止复制的位置,这一样会有一个问题,若是master.info不正确,就会致使复制数据不一致的状况,遇到这个问题怎么办?

答:这个问题能够经过两种方式解决,一是控制master.info在从库非计划关闭或重启的时候让master.info可以同步到磁盘,这样下次启动的时候就不会读取错误的信息,这有助于减小错误的发生几率。另外想要找到正确的复制位置是困难的,咱们也能够选择忽略错误。


……


其实问题也是蛮多的,这里就再也不继续提问了,包括若是主库二进制日志文件损坏怎么办?从库中继日志文件损坏怎么办?由于每一个环节都不是百分之一百可靠的,所以咱们必须对可能遇到的问题提出假设,思考解决方案。本文经过黄金圈法则提出的三个问题来认识MySQL复制,经过自问自答的形式来对主体的一些可能存在的应用问题进行讨论,对于复制方面还存在不少的实际应用问题,这里只是抛砖引玉,还请数据库大牛们多多指教。

相关文章
相关标签/搜索