在我们工作中,一般都会使用一个最基础的一主一从数据库集群,这样可以避免单机故障,业务发展到一定程度的时候还可以进行读写分离。

既然数据库有了主从,那么主从之间的数据一致性就必须是我们要解决的一个问题

MySql主从复制原理

在主从进行同步过程中会涉及到三个线程:

  • 从库的I/O线程:主要是获取主库的binlog日志,获取到日志之后将日志写到relay log日志文件中
  • 从库的sql线程:读取relay log日志内容,解析成sql执行,其实就是执行主库的sql
  • 主库的log dump线程:读取主库的新增的binlog日志文件内容,发送给从库
  • 那么有哪些点是会造成主从数据延迟呢?

    从库机器配置比主库差

    很多人以为主库的压力会比从库压力大,其实不是的,回顾主从复制原理我们可以知道主库执行一次SQL操作,那么从库对应的就要执行日志的回放重写,再执行SQL,甚至进行读写分离的时候,从库的压力甚至比主库的大很多。

    无论是读取主库的binlog,还是回放SQL,那么都需要消耗机器的资源,无论是内存还是CPU,如果从库的配置很差,那么相对应的执行这些操作的时候所耗费的时间就会更长,那么主从之间的数据延迟就会加大

    MySql数据锁会被很多人忽略掉,就在想, 为什么会造成主从数据的延迟呢? 比如说主库执行了二条SQL

    update t_user set name = '章三' where name = '里斯'
    update t_user set first_name = '王五' where first_name = 'admin'
    

    那么从库也是按这种顺序去回放这二条SQL,这时候问题就来了,如果这个时候 name 字段没有索引,那么这时候MySql就会升级为表锁,这时候当主库都更新完这二条数据之后,binlog发送到从库进行回放

    这时候执行 update t_user set name = '章三' where name = '里斯',那么从库也会升级为表锁,这时候从库执行这条SQL就会花费很长时间,在这条SQL没有执行完,第二条SQL是不会执行的,这时候主从之间就会造成较大的数据延迟了,因为你主库是已经更新好了,但是从库执行的时候发生了锁表操作,导致花费的时间很长

    大事务会造成主从数据延迟的原理与是一样的,大事务指的是:操作流程多,话费时间长的一些事务。这时候这个事务在从库进行回放的时候,也会话费很长的时间。在这个事务没有完成前,后面的SQL操作都没办法执行,就会造成主从之间的数据延迟

    DDL操作

    我们经常碰到在系统跑了一段时间之后,由于加了需求或者其它原因,需要对表结构进行一下更改。也就是DDL操作,这个操作是会把整张表都锁住的。如果这时候主库进行了DDL操作,那么从库相应的也要进行DDl操作,从库在执行DDL操作的时候,那么其它相关的SQL就没办法执行。就必须等到这个DDL操作完成之后再执行,如果这个DDL操作花费时间很长,那么主从之间的数据延迟就会很大

    所以这里建议不要再系统一开始就做主从配置,等系统稳定了一段时间之后再做主从,这样可以避免由于DDL操作带来的主从数据延迟甚至是一些未知的错误

    很多面试题都会说主从之间的复制说主库是多线程写,从库是单线程读,这样就会造成主从数据延迟,但是现在MySql出了并行复制之后,其实这个对主从之间的数据延迟影响很小很小了。

    会造成MySql主从数据延迟主要有:从库机器配置比主库差,锁,大事务,DDL操作等,所以在平时工作中做了主从的一定要注意这个几个点,防止因为主从数据延迟带来一些业务问题