简介:主库与从库之前同步数据是通过一个长连接来实现的,主库内部有一个线程,专门维护从库的这个长连接。如果主库和从库数据同步时,这个长连接突然中断了怎么办?还有删除数据时使用了limit和order by排序,但是索引问题导致主从删除的数据不一致怎么办?
今天的主题是MySQL主从一致及主从同步延时的问题,解决这个问题之前我们需要了解什么是主从及主从复制的原理。大家可以看看我之前的【MySQL主从复制-基于binlog日志】的文章。
1.如何保证主从一致
主库与从库之前同步数据是通过一个长连接来实现的,主库内部有一个线程,专门维护从库的这个长连接。如果主库和从库数据同步时,这个长连接突然中断了怎么办?还有删除数据时使用了limit和order by排序,但是索引问题导致主从删除的数据不一致怎么办?
我们先来看看下面的删除SQL:
delete from orders where status < 0 and create_time<'2023-04-21' limit 1;
SQL执行时选择了 status 索引和选择 create_time 索引,最后 limit 1 出来的数据是不一样的。如果我们是基于binlog日志实现的主从同步并且 binlog=statement 格式时,主库执行这条SQL时,使用的是索引 status ,同步到从库执行这条SQL时,使用了索引 create_time ,最后导致主从数据不一致。
对于这一类的主从不一致的问题我们可以将 binlog 改为 row 格式。因为row格式记录的不是SQL原文,而是两个事件table_map 和 delete_rows 。row格式的binlog记录的就是要删除的主键ID信息,因此不会出现主从不一致的问题。
不过这种方法有一个很大的缺点,占用空间大。
假设SQL删除10万行数据,10万条数据都在 binlog 里面,写binlog的时候也很耗IO。于是MySQL就出现了一个折中方案,mixed格式的binlog。其实就是row和statement格式的混合,当MySQL判断可能数据不一致时,就使用row格式,否则使用statement格式
2.主从延迟
有时候我们写入主库后再去从库读取数据时,发现读取不到数据,但是过了一会儿又可以读取到数据,这基本就是主从延迟导致的。
上面我们说过了主库通过一个长连接来实现同步数据到从库,但是这个同步的过程需要经过网络传输,从库解析并执行SQL,这个过程是需要一定的时间。在这个同步的时间内会导致从库查询的数据和主库不一致。
注意:主库的TPS并发较高时,产生的DDL数量超过从库同步的SQL线程所能承受的范围,延迟会更严重。
如果从库的一些query语句产生了锁等待时,也会导致延迟。毕竟加锁后同步的线程无法执行同步SQL。
如果大家不了解主从复制原理的可以看看我之前的【MySQL主从复制-基于binlog日志】的文章。
2.1 主从延迟解决方案
解决这类问题,除了缩短主从延迟的时间,还有一些其他的办法,基本原理都是尽量不查询从库,具体方案如下:
在实际应用场景中,对于一些非常核心的场景,比如库存,支付订单等直接查询主库,其它非核心场景可以查询从库。
有遗漏或者不对的可以在我的公众号留言哦