主要是因为MySQL在主从复制的过程是通过bin log 进行数据同步的,而MySQL早期只有statement这种bin log格式,这种格式下,bin log记录的是SQL语句的原文。
当出现事务乱序的时候,就会导致备库在 SQL 回放之后,结果和主库内容不一致。
为了解决这个问题,MySQL默认采用了Repetable Read这种隔离级别,因为在 RR 中,会在更新数据的时候增加记录锁的同时增加间隙锁。可以避免这种情况的发生。

RR和RC的区别

一致性读

一致性读,又叫快照读,快照即当前数据之前的历史版本。快照读就是使用快照信息显示基于某个时间点的查询结果,而不考虑与此同时运行的其他事务所执行的修改。
Mysql中只有RR和RC才有快照读。

在RC中,每次读取都会重新生成一个快照,总是读取行的最新版本; 在RR中,快照会在事务中第一次select语句执行时生成,只有在本事务中对数据进行变更才会更新快照。

在RC这种隔离级别中,还支持“半一致读”,一条update语句,如果where条件匹配到的记录都已经加锁,那么InnoDB会返回记录最近提交的版本,由mysql上层判断此是否需要真的加锁。

锁机制

数据库的锁,在不同的事务隔离级别下,是采用了不同的机制的。在mysql中,有三类锁:Record Lock , gap Lock, Next-key Lock

Record Lock表示记录锁,锁的是索引记录 Gap Lock 是间隙锁,锁的是索引记录之间的间隙 Next-key Lock,是记录锁和间隙锁的组合,同时锁索引记录和间隙,范围是左开右闭的。

在RC中,只对索引增加Record Lock,不会添加Gap Lock和Next-key Lock;
在RR中,为了解决幻读的问题,在支持Record Lock的同时,还支持gap Lock和Next-key Lock;

主从同步

在数据主从同步时,不同格式的binlog也对事务隔离级别有要求。
Mysql binlog主要支持三种格式,分别是statement 、row 、 mixed, 但是RC级别只支持row格式的binlog.
RR 同时支持三种。

为什么互联网公司选择RC?

提升并发

RC在加锁的过程中,不需要添加间隙锁和next-key lock,只需要修改记录并添加行级锁就可以了。
RC还支持半一致读,可以大大减少更新语句的行锁冲突,对于不满足更新条件的记录,可以提前释放锁,提升并发度。

减少死锁

RR这种增加gap lock和Next-key lock,使得锁的粒度变大,那么就会使得死锁的概率增加。