一、什么叫mysql复制?

   关于mysql复制,我是这样理解的:将某一台主机上的Mysql数据复制到其它主机(slaves)上,并重新执行一遍从而实现当前主机上的mysql数据与(master)主机上数据保持一致的过程我们可以称为复制。

   复制过程中一个服务器充当主服务器,而一个或多个其它服务器充当从服务器。主服务器将更新写入二进制日志文件,并维护文件的一个索引以跟踪日志循环。这些日志可以记录发送到从服务器的更新。当一个从服务器连接主服务器时,它通知主服务器从服务器在日志中读取的最后一次成功更新的位置。从服务器接收从那时起发生的任何更新,然后封锁并等待主服务器通知新的更新。


二、mysql复制是如何工作的?

Mysql主从架构的复制原理及配置详解_第1张图片

   从上图看mysql的主从复制整体来说分为3个部分:

   1、master将状态信息的改变记录到二进制日志(binary log)中(这些记录叫做二进制日志事件,binary log events);

   2、slave将master的binary log events拷贝到它的中继日志(relay log);

   3、slave重做中继日志中的事件,将状态信息的改变存储到本地磁盘行成数据;


   详细描述如下:

   首先该过程的第一部分就是master记录二进制日志。在每个事务更新数据完成之前,master在二日志记录这些改变。MySQL将事务串行的写入二进制日志,即使事务中的语句都是交叉执行的。在事件写入二进制日志完成后,master通知存储引擎提交事务。

   接下来就是slave将master的binary log拷贝到它自己的中继日志。先是slave开始一个工作线程——I/O线程,I/O线程在master上打开一个普通的连接,然后开始binlog dump process从master的二进制日志中读取事件,如果已经跟上master,它会睡眠并等待master产生新的事件(Seconds_Behind_Masterk可以观察落后的状态),I/O线程将这些事件写入中继日志。

   最后SQL thread(SQL从线程)从中继日志读取事件,并执行事件语句更新slave的数据,使其与master中的数据一致。


   此外,在master中也有一个工作线程:和其它MySQL的连接一样,slave在master中打开一个连接也会使得master开始一个线程。复制过程有一个很重要的限制——复制在slave上是串行化的,也就是说master上的并行更新操作不能在slave上并行操作(slave会有数据上的延时)。


三、复制能解决的问题及mysql支持的复制类型:

   1、MySQL复制技术有以下一些好处:

       1.1、数据分布 (Data distribution )

       1.2、可以实现负载均衡(load balancing),通常所说的读写分离

       1.3、可以实现数据的备份(Backups),但是不能当真正意义上数据备份来用

       1.4、高可用性和容错行(比如双主模型中的互为主从能实现高可用)

   2、复制类型:

       2.1、基于语句的复制(statement):在主服务器上执行的SQL语句,在从服务器上执行同样的语句。

            优点:基于语句的复制,效率比较高;需要注意地方:可能无法精确复制,比如sql中更新时间的时候如果不是精准值而是time();什么的,由于主从复制有延时导致数据的不一致。

       2.2、基于行的复制(row):把改变的内容复制过去,而不是把命令在从服务器上执行一遍。数据复制相对安全,但是产生的日志文件会过大,比如update某一范围来数据的状态,这个范围有1W条数据,就会产生1W条update语句;

       2.3、混合类型的复制(mixed): mysql5.5默认采用混合类型的复制,也就是上面的两种根据情况变换着复制。此方法可能会打乱日志的结构,一会基于语句一会儿基于行,日志排查日志的可能看起来不太好使;

   3、mysql复制中需要注意的问题:

       3.1、主从服务器mysql的版本,主库的版本可以低于从库,但是从库的版本一定不能低于主库(从版本 >= 主版本)

       3.2、为了复制的安全额外设置:

               从服务器:

                   read_only=ON              关闭写

                   skip-slave-start=ON       关闭从服务自动启动

               主服务器:

                   sync_binlog=ON            同步事务的二进制日志


四、主从复制的配置:

 1、主从服务器各自需要的准备操作  

       1.1、主服务器:

           a、创建具有复制权限的用户帐号;

mysql> grant replication slave, replication client on *.* to copyuser@'172.16.5.%' identified by '123456';

               mysql> flush privileges;

           b、设置server-id;

# server-id = 10

           c、启用二进制日志;

# log-bin = /mydata/log/mysql-bin        日志存放位置

# binlog_format = row                    基于行复制


       1.2、从服务器:

           a、启用中继日志;(可选:关闭二进制日志)

               # relay-log = /mydata/log/relay-bin     日志存放位置

               # read-only = 1                         设置为只读(对root权限账号无效)

           b、设置server-id;

               # server-id = 20

           c、启动复制线程;

               # change master to master_host='172.16.5.100' master_user='copyuser' master_password='123456'

               # slave start;

               查看状态:

               # show slave status\G;

               # show processlist;

               在这里主要是看:

Slave_IO_Running = Yes

               Slave_SQL_Running = Yes

               如果需要只复制某些库可以指定过滤条件;

               replicate-do-db        = db1,db2      只复制某库

               replicate-do-table     = db1.mytbl    只复制某库某表

               replicate_ignore_db    = db3          不复制某库

               replicate_ignore_table = db1.nytb3    不复制某库中的某表


五、深入了解复制

   1、一主多从

       由一个master和一个slave组成复制系统是最简单的情况。Slave之间并不相互通信,只能与master进行通信。在实际应用场景中,MySQL复制90%以上都是一个Master复制到一个或者多个Slave的架构模式,主要用于读压力比较大的应用的数据库端廉价扩展解决方案。

Mysql主从架构的复制原理及配置详解_第2张图片

       在上图中,如果一主拖了多个从的话,这时主库既要负责写又要负责为几个从库提供二进制日志,此时可以稍做调整,将二进制日志只给某一从,这一从再开启二进制日志并将自己的二进制日志再发给其它从,或者是干脆这个从不记录只负责将二进制日志转发给其它从,这样架构起来性能可能要好得多,而且数据之间的延时应该也稍微要好一些。


   2、主主复制

Mysql主从架构的复制原理及配置详解_第3张图片

       上图中,Master-Master复制的两台服务器,既是master,又是另一台服务器的slave。这样,任何一方所做的变更,都会通过复制应用到另外一方的数据库中。在这种复制架构中,各自上运行的不是同一db,比如左边的是db1,右边的是db2,db1的从在右边反之db2的从在左边,两者互为主从,再辅助一些监控的服务还可以实现一定程度上的高可以用。


   3、主动-被动模式(HA)

Mysql主从架构的复制原理及配置详解_第4张图片

       上图中,这是由master-master结构变化而来的,它避免了M-M的缺点,实际上,这是一种具有容错和高可用性的系统。它的不同点在于其中只有一个节点在提供读写服务,另外一个节点时刻准备着,当主节点一旦故障马上接替服务。比如通过corosync+pacemaker+drbd+mysql就可以提供这样一组高可用服务,主备模式下再跟着slave服务器,也可以实现读写分离。


   4、mysql-5.5支持半同步复制

       mysql复制我们都知道是基于异步来实现的,但是从mysql-5.5开始,支持半自动复制。在以前版本中异步(asynchronous)复制中,主库在执行完一些事务后,是不会管备库的进度的。如果备库处于落后,而更不幸的是主库此时又出现Crash(例如宕机),这时备库中的数据就是不完整的。简而言之,在主库发生故障的时候,我们无法使用备库来继续提供数据一致的服务了。Semisynchronous Replication(半同步复制)则一定程度上保证提交的事务已经传给了至少一个备库。Semi synchronous中,仅仅保证事务的已经传递到备库上,但是并不确保已经在备库上执行完成了。

       此外,还有一种情况会导致主备数据不一致。在某个session中,主库上提交一个事务后,会等待事务传递给至少一个备库,如果在这个等待过程中主库Crash,那么也可能备库和主库不一致,这是很致命的。如果主备网络故障或者备库挂了,主库在事务提交后等待10秒(rpl_semi_sync_master_timeout的默认值)后,就会继续。这时,主库就会变回原来的异步状态。

MySQL在加载并开启Semi-sync插件后,每一个事务需等待备库接收日志后才返回给客户端。如果做的是小事务,两台主机的延迟又较小,则Semi-sync可以实现在性能很小损失的情况下的零数据丢失。