一、什么叫mysql复制?
关于mysql复制,我是这样理解的:将某一台主机上的Mysql数据复制到其它主机(slaves)上,并重新执行一遍从而实现当前主机上的mysql数据与(master)主机上数据保持一致的过程我们可以称为复制。
复制过程中一个服务器充当主服务器,而一个或多个其它服务器充当从服务器。主服务器将更新写入二进制日志文件,并维护文件的一个索引以跟踪日志循环。这些日志可以记录发送到从服务器的更新。当一个从服务器连接主服务器时,它通知主服务器从服务器在日志中读取的最后一次成功更新的位置。从服务器接收从那时起发生的任何更新,然后封锁并等待主服务器通知新的更新。
二、mysql复制是如何工作的?
从上图看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的架构模式,主要用于读压力比较大的应用的数据库端廉价扩展解决方案。
在上图中,如果一主拖了多个从的话,这时主库既要负责写又要负责为几个从库提供二进制日志,此时可以稍做调整,将二进制日志只给某一从,这一从再开启二进制日志并将自己的二进制日志再发给其它从,或者是干脆这个从不记录只负责将二进制日志转发给其它从,这样架构起来性能可能要好得多,而且数据之间的延时应该也稍微要好一些。
2、主主复制
上图中,Master-Master复制的两台服务器,既是master,又是另一台服务器的slave。这样,任何一方所做的变更,都会通过复制应用到另外一方的数据库中。在这种复制架构中,各自上运行的不是同一db,比如左边的是db1,右边的是db2,db1的从在右边反之db2的从在左边,两者互为主从,再辅助一些监控的服务还可以实现一定程度上的高可以用。
3、主动-被动模式(HA)
上图中,这是由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可以实现在性能很小损失的情况下的零数据丢失。