Mysql之主从复制
主从复制过程
主从复制大概分三个过程:
-
MySQL 主库在收到客户端提交事务的请求之后,会先写入 binlog,再提交事务,更新存储引擎中的数据,事务提交完成后,返回给客户端“操作成功”的响应。
-
从库会创建一个专门的 I/O 线程,连接主库的 log dump 线程,来接收主库的 binlog 日志,再把 binlog 信息写入 relay log 的中继日志里,再返回给主库“复制成功”的响应。
-
从库会创建一个用于回放 binlog 的线程,去读 relay log 中继日志,然后回放 binlog 更新存储引擎中的数据,最终实现主从的数据一致性。
MySQL主从复制的模型
主要有三种;
-
同步复制:事务线程要等待所有从库的复制成功响应。
-
异步复制:事务线程完全不等待从库的复制成功响应。
-
半同步复制:MySQL 5.7 版本之后增加的一种复制方式,介于两者之间,事务线程不用等待所有的从库复制成功响应,只要一部分复制成功响应回来就行,比如一主二从的集群,只要数据成功复制到任意一个从库上,主库的事务线程就可以返回给客户端。
如何查看同步延迟状态?
在从服务器上通过 show slave status 查看具体的参数,有几个参数比较重要:
- master_log_file: slave中的IO线程正在读取的主服务器二进制日志文件的名称
- read_master_log_pos: 在当前的主服务器二进制日志中,slave中的IO线程已经读取的位置
- relay_log_file: sql线程当前正在读取和执行的中继日志文件的名称
- relay_log_pos: 在当前的中继日志中,sql线程已经读取和执行的位置
- relay_master_log_file: 由sql线程执行的包含多数近期事件的主服务器二进制日志文件的名称
- slave_io_running: IO线程是否被启动并成功的连接到主服务器上
- slave_sql_running: sql线程是否被启动
- seconds_behind_master: 从属服务器sql线程和从属服务器IO线程之间的事件差距,单位以秒计
主从延迟的时间
根据前面主从复制的原理可以看出,两者之间是存在一定时间的数据不一致,也就是所谓的主从延迟。
我们来看下导致主从延迟的时间点:
- 主库 A 执行完成一个事务,写入 binlog,该时刻记为T1。
- 传给从库B,从库接受完这个binlog的时刻记为T2。
- 从库B执行完这个事务,该时刻记为T3。
那么所谓主从延迟,就是同一个事务,从库执行完成的时间和主库执行完成的时间之间的差值,即T3-T1。我们也可以通过在从库执行show slave status,返回结果会显示seconds_behind_master,表示当前从库延迟了多少秒。SBM在进行计算的时候也是按照这样的方式,每个事务的binlog中都有一个时间字段,用于记录主库写入的时间,备库取出当前正在执行的事务的时间字段的值,计算它与当前系统时间的差值,得到SBM。
seconds_behind_master如何计算的?
- 每一个事务的binlog都有一个时间字段,用于记录主库上写入的时间
- 从库取出当前正在执行的事务的时间字段,跟当前系统的时间进行相减,得到的就是seconds_behind_master,也就是前面所描述的T3-T1。
主从延迟原因
1、从库的机器性能比主库要差
比如将20台主库放在4台机器,把从库放在一台机器。这个时候进行更新操作,由于更新时会触发大量读操作,导致从库机器上的多个从库争夺资源,导致主从延迟。不过,目前大部分部署都是采取主从使用相同规格的机器部署。
2、从库的压力大
按照正常的策略,读写分离,主库提供写能力,从库提供读能力。将进行大量查询放在从库上,结果导致从库上耗费了大量的CPU资源,进而影响了同步速度,造成主从延迟。
对于这种情况,可以通过一主多从,分担读压力;也可以采取binlog输出到外部系统,比如Hadoop,让外部系统提供查询能力。
3、大事务的执行
一旦执行大事务,那么主库必须要等到事务完成之后才会写入binlog。
比如主库执行了一条insert … select非常大的插入操作,该操作产生了近几百G的binlog文件传输到只读节点,进而导致了只读节点出现应用binlog延迟。
因此,DBA经常会提醒开发,不要一次性地试用delete语句删除大量数据,尽可能控制数量,分批进行。
4、主库的DDL(alter、drop、create)
只读节点与主库的DDL同步是串行进行,如果DDL操作在主库执行时间很长,那么从库也会消耗同样的时间,比如在主库对一张500W的表添加一个字段耗费了10分钟,那么从节点上也会耗费10分钟。
从节点上有一个执行时间非常长的的查询正在执行,那么这个查询会堵塞来自主库的DDL,表被锁,直到查询结束为止,进而导致了从节点的数据延迟。
5、锁冲突
锁冲突问题也可能导致从节点的SQL线程执行慢,比如从机上有一些select .... for update的SQL,或者使用了MyISAM引擎等。
6、从库的复制能力
一般场景中,因偶然情况导致从库延迟了几分钟,都会在从库恢复之后追上主库。但若是从库执行速度低于主库,且主库持续具有压力,就会导致长时间主从延迟,很有可能就是从库复制能力的问题。
参考和转载
https://blog.csdn.net/weixin_42678790/article/details/119910902
https://www.cnblogs.com/ityml/p/14961571.html
https://developer.aliyun.com/article/894940