sql复制⼀条数据并修改_MySQL⼊门(5):复制
摘要
在这篇⽂章中,我将从MySQL为什么需要主从复制开始讲起,然后会提到MySQL复制的前提,bin log。
在这⾥会说明三种格式的bin log分别会有什么优缺点。
随后会讲到主从延迟⽅⾯的问题,我将从⼏个⾓度出发,提供⼀些可能造成延迟的思路。
mysql删除重复的数据保留一条
1 为什么需要复制
MySQL内建的复制功能是构建⼤型,⾼性能应⽤程序的基础。随着⽬前并发量的增加,单机的MySQL渐渐没有办法承担这些请求,所以MySQL服务器也需要进⾏扩展。
MySQL的复制功能不仅可以提⾼可⽤性,还能⽤作灾备,数据仓库等。
2 如何复制
说到复制,那么问题的关键就在于数据从主库复制到从库时间需要多少,准确度能有多⾼。
对于MySQL来说,复制使⽤的是bin log。
对于bin log相信你不会陌⽣,我们在聊到MySQL的“两阶段提交”的时候有说到这个。
也就是说,MySQL会将主库记录的bin log发送到从库中,然后从库按照bin log的内容,“重放⼀遍”主库执⾏过的操作,达到主从同步的⽬的。
在这⾥我们先详细说⼀说bin log记录了什么。
2.1 SBR(statement-based replication)
在这种模式下,bin log会完整的记录下所执⾏的SQL语句。也就是说,如果使⽤了statement格式的bin log的话,主库执⾏的SQL语句就会在从库中完整的再执⾏⼀遍。
主从不⼀致的。
可是,这样的做法,是有可能导致主从不⼀致
例如下⾯这样的语句:
delete from t where a >= 1 and b => 2 limit 1;
这样的语句在从库中就不⼀定能够实现跟主库⼀样的效果。因为我们不能够确定在从库中是否⾛的跟主库是同样的索引,所查的第⼀条数据,是不是跟主库⼀样的,也就可能删除的数据不是同⼀⾏。
⼜或者主库执⾏的SQL语句⾥⾯有⼀些锁相关的语句,也可能会造成主从不⼀致的问题。
但是要注意的是,NOW()函数是可以被正确执⾏的,因为在bin log语句中会记录时间戳。
也就是说,基于statement模式,在上下⽂不同的时候,是有可能造成数据不⼀致的。
⾄于其他的不安全情况,可以参考官⽅⽂档,这⾥不展开介绍。
2.2 RBR(row-based replication)
既然statement模式下会造成数据不⼀致,那么有没有⼀种模式是上下⽂⽆关的呢?
所以就有了row模式。
在这个模式中,bin log中只记录了所操作的⾏的修改情况,会精确到某⼀⾏。
⽐如你更新了某⼀⾏,在bin log中就会记录在id等于多少多少,某某字段等于多少多少的⾏中,将某个字段的值从A改成了B。
甚⾄是删除操作,都会记录删除了id等于多少,A字段等于多少,B字段等于多少的⼀⾏数据。
听到这⾥你可能会觉得很⽅便,也很精确,主从不再会发⽣不⼀致的情况了。甚⾄于删库了都不需要跑路了,只需要查看bin log就能恢复相应的数据了。
但是使⽤row模式同样会有⼀些问题。⽐如你在主库执⾏了delete from t where id < 10000这么⼀⾏sql语句,如果使⽤statement格式,在bin log内记录只有这么⼀条,但是如果你使⽤的是row模式,那么就需要记录10000条数据,占⽤很⼤的空间。
2.3 MBR(mixd-based replication)
于是就有了mixd模式。
混合了以上两种模式的优点,MySQL会在没有歧义的时候使⽤statement格式,在有歧义的时候使⽤row格式。
3 复制的具体过程
上⾯介绍了bin log的作⽤,以及bin log的组成形式,在这⼀章中我们聊⼀聊整个的复制流程。
我们拿《⾼性能MySQL》中的图来解释:
这⾥涉及到了有三个线程:
Binlog dump thread
这个线程在MySQL主库中,负责读取bin log中的内容,并将这些内容推送到从库IO进程中。
I/O thread
这个线程在MySQL从库中,负责跟主库建⽴⼀条长连接,并且将读取到的bin log数据保存到从库的中继⽇志(relay log)中。
SQL thread
这个线程也是在MySQL的从库中,负责读取中继⽇志中的内容,然后执⾏这些语句,将对数据的修改应⽤到从库中。
简单的来讲,就是主库经过两阶段提交后,把修改内容保存在了bin log中,然后把这个bin log发送给从库,让从库也执⾏⼀次,以达到同步的⽬的。
⽽这⾥采⽤了中继⽇志的原因是从库消费bin log的速度和主库⽣产bin log的速度是不⼀致的,所以需要⼀个中继⽇志作为缓冲。
4 复制可能造成的问题
延迟。
在MySQL复制的过程中,经常出现的问题是延迟
假设我们把主库⼀个事务提交后bin log落盘的时间点设为t1
把从库接受到主库新事务写的bin log并写⼊relay log的时间节点设为t2
把从库执⾏完这个新的事务的时间节点设为t3
那么执⾏⼀条事务,从库的延迟可以认为是(t3 - t1)。
也就是说,如果我们需要分析造成主从延迟的原因,应该从两个⽅⾯考虑:传输过程,以及从库消费relay log的速度。
4.1 ⽹络问题
⽹络确实可能会造成主从延迟,⽐如主库或者从库的带宽打满,⼜或者是主库的bin log被设置成了row格式,导致有⼤量的数据需要传输,造成了主库的bin log没有及时的同步到从库中,导致了主从的延迟。
4.2 机器性能
但是除了⽹络,更多的是从库的消费速度,跟不上主库的⽣产速度。
这⽅⾯有很多原因,⽐如可能从库的机器配置低于主库,因为会有⼈觉得既然是备库,没什么请求,就把备库配置在了⽐较差的机器上⾯。
⼜或者在是后台的数据分析,将CPU打满。
总之,如果在从库中需要有⼤量的查询分析操作,需要考虑多个从库。
4.3 ⼤事务
如果主库执⾏了⼀条耗时很长的事务,那么这条事务发送到从库中,可能也需要执⾏这么长的时间。⽽这个时候,从库是没有办法继续消费新的relay log的。这就造成了主从延迟。
4.4 锁
我们之前提到过了,不仅仅写数据会加锁,使⽤“当前读”,也⼀样可能会加锁。
所以,如果在从库上执⾏了⼀些诸如select ... for update,或者⼀些DDL语句,可能也会造成从库加锁,导致主从延迟。
4.5 并发
在我们上⾯的介绍中,SQL线程是单线程的,所以,如果能够让SQL线程可以并发消费,那么主从延迟就可以⼤幅度的降低了。
关于MySQL的并发复制策略,MySQL5.6开始已经正式⽀持了,本⽂不详细解释。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。