谈谈mySql主从复制

300 阅读8分钟

本文已参与掘金创作者训练营第三期「话题写作」赛道,详情查看:掘力计划|创作者训练营第三期正在进行,「写」出个人影响力

什么是mysql的主从复制

指一台服务器充当主数据库服务器,另一台或多台服务器充当从数据库服务器,主服务器中的数据自动复制到从服务器之中。对于多级复制,数据库服务器即可充当主机,也可充当从机。MySQL主从复制的基础是主服务器对数据库修改记录二进制日志,从服务器通过主服务器的二进制日志自动执行更新。 即主数据库做什么,从数据库就跟着做什么。

mysql复制原理

master服务器将数据的改变记录二进制binlog日志,当master上的数据发生改变时,则将其改变写入二进制日志中;

slave服务器会在一定时间间隔内对master二进制日志进行探测其是否发生改变,如果发生改变,则开始一个I/OThread请求master二进制事件

同时主节点为每个I/O线程启动一个dump线程,用于向其发送二进制事件,并保存至从节点本地的中继日志中,从节点将启动SQL线程从中继日志中读取二进制日志,在本地重放,使得其数据和主节点的保持一致,最后I/OThread和SQLThread将进入睡眠状态,等待下一次被唤醒。如图所示:

主从.PNG

主从复制三个线程

主节点:dump Thread:为每个Slave的I/O Thread启动一个dump线程,用于向其发送binary log events

从节点:I/O Thread:向Master请求二进制日志事件,并保存于中继日志中,SQL Thread:从中继日志中读取日志事件,在本地完成重放

复制过程:

主库开启binlog,将主库现有的库导入到从库。从库开启同步,指定上次导入数据的位置记录。从库的IO线程向主库请求从指定的binlog日志文件的指定位置之后的binlog日志内容。主库收到请求,负责复制的IO线程去读取指定的binlog日志内容,然后将内容,以及本次返回日志内容的下一个更新位置一起返回给从库的IO线程。从库收到日志,依次写入中继日志(relay log)中,并将新的binlog文件名和位置记录到master-info文件中。以便下一次同步。 从库的SQL线程会实时检测中继日志的内容,然后及时的把日志中的SQL语句按顺序执行。

mysql复制的方式和类型

主从同步复制类型

同步复制

在 MySQL cluster 中特有的复制方式。 当主库执行完一个事务,然后所有的从库都复制了该事务并成功执行完才返回成功信息给客户端。 因为需要等待所有从库执行完该事务才能返回成功信息,所以全同步复制的性能必然会收到严重的影响。

异步复制

master只需要完成自己的数据库操作即可,至于slaves是否收到二进制日志,是否完成操作,不用关心。MYSQL的默认设置。这种模式下,主节点不会主动推送数据到从节点,主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已经接收并处理。 这样就会有一个问题,主节点如果崩溃掉了,此时主节点上已经提交的事务可能并没有传到从节点上,如果此时,强行将从提升为主,可能导致新主节点上的数据不完整。

半同步复制

在异步复制的基础上,确保任何一个主库上的事物在提交之前至少有一个从库已经收到该事物并日志记录下来。介于异步复制和全同步复制之间,主库在执行完客户端提交的事务后不是立刻返回给客户端,而是等待至少一个从库接收到并写到relay log 中才返回成功信息给客户端(只能保证主库的 Binlog 至少传输到了一个从节点上),否则需要等待直到超时时间然后切换成异步模式再提交。

相对于异步复制,半同步复制提高了数据的安全性,一定程度的保证了数据能成功备份到从库,同时它也造成了一定程度的延迟,但是比全同步模式延迟要低,这个延迟最少是一个 TCP/IP 往返的时间。所以,半同步复制最好在低延时的网络中使用。 半同步模式不是 MySQL 内置的,从 MySQL 5.5 开始集成,需要 master 和 slave 安装插件开启半同步模式。

mysql复制的方式

语句复制

基于语句的复制相当于逻辑复制,即二进制日志中记录了操作的语句,通过这些语句在从数据库中重放来实现复制。

这种方式简单,二进制文件小,传输带宽占用小。但是基于语句更新依赖于其它因素,比如插入数据时利用了时间戳。

因此在开发当中,我们应该尽量将业务逻辑逻辑放在代码层,而不应该放在 MySQL 中,不易拓展。

特点:

传输效率高,减少延迟。

在从库更新不存在的记录时,语句赋值不会失败。而行复制会导致失败,从而更早发现主从之间的不一致。

设表里有一百万条数据,一条sql更新了所有表,基于语句的复制仅需要发送一条sql,而基于行的复制需要发送一百万条更新记录

行数据复制

基于行的复制相当于物理复制,即二进制日志中记录的实际更新数据的每一行。

这样导致复制的压力比较大,日志占用的空间大,传输带宽占用大。但是这种方式比基于语句的复制要更加精确。

特点:

不需要执行查询计划。

不知道执行的到底是什么语句。

例如一条更新用户总积分的语句,需要统计用户的所有积分再写入用户表。如果是基于语句复制的话,从库需要再一次统计用户的积分,而基于行复制就直接更新记录,无需再统计用户积分。

混合复制

上面两个结合体,默认用语句复制,出问题时候自动切换成行数据复制。

相对应的日志格式也有三种:STATEMENT,ROW,MIXED。

1.STATEMENT模式(SBR) 每一条会修改数据的sql语句会记录到binlog中。优点是并不需要记录每一条sql语句和每一行的数据变化,减少了binlog日志量,节约IO,提高性能。缺点是在某些情况下会导致master-slave中的数据不一致(如sleep()函数, last_insert_id(),以及user-defined functions(udf)等会出现问题)

ROW模式(RBR) 不记录每条sql语句的上下文信息,仅需记录哪条数据被修改了,修改成什么样了。而且不会出现某些特定情况下的存储过程、或function、或trigger的调用和触发无法被正确复制的问题。缺点是会产生大量的日志,尤其是alter table的时候会让日志暴涨。

MIXED模式(MBR) 以上两种模式的混合使用,一般的复制使用STATEMENT模式保存binlog,对于STATEMENT模式无法复制的操作使用ROW模式保存binlog,MySQL会根据执行的SQL语句选择日志保存方式。

配置主从复制

主服务器配置

1、开启bin-log

2、设置唯一的server id

3、授权一个账号给从,可以从主复制数据

4、备份数据库,传给从,因为同步初始阶段,主从的数据要一致

从服务器配置

1、设置server id

2、导入数据

3、指定主节点,并连到主服务器的账号

主从复制的优点

实现负载均衡

一主多从相当于分担了主机任务,做了负载均衡。

数据更安全

可以定期的将数据从主服务器上复制到从服务器上,数据更安全:做了数据冗余,不会因为单台服务器的宕机而丢失数据;

提高数据库系统的可用性

流量增大时,可以方便的增加从服务器,不影响系统使用。

主从复制的问题

延迟

当主库的TPS并发较高的时候,由于主库上面是多线程写入的,而从库的SQL线程是单线程的,导致从库SQL可能会跟不上主库的处理速度。解决方法:网络方面:尽量保证主库和从库之间的网络稳定,延迟较小;硬件方面:从库配置更好的硬件,提升随机写的性能;配置方面:尽量使 MySQL 的操作在内存中完成,减少磁盘操作。或升级 MySQL5.7 版本使用并行复制;建构方面:在事务中尽量对主库读写,其它非事务的读在从库。消除一部分延迟带来的数据库不一致。增加缓存降低一些从库的负载。

数据丢失

当主库宕机后,数据可能丢失。解决方法:使用半同步复制,可以解决数据丢失的问题。