为什么mysql的默认隔离级别是可重复读

157 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。


来源

www.cnblogs.com/rjzheng/p/1…

这个是有历史原因的,mysql是基于binlog的主从复制

binlog有三种格式,分别是

statement:记录的是修改SQL语句

row:记录的是每行实际数据的变更

mixed:statement和row模式的混合

Mysql在5.0这个版本以前,binlog只支持STATEMENT这种格式,而这种格式在读已提交(Read Commited)这个隔离级别下主从复制是有bug的,因此Mysql将可重复读(Repeatable Read)作为默认的隔离级别!

1. STATEMENT 主从复制的bug是什么****

就是在master上执行的顺序为先删后插!而此时binlog为STATEMENT格式,它记录的顺序为先插后删!从(slave)同步的是binglog,因此从机执行的顺序和主机不一致!就会出现主从不一致!【顺序颠倒】

2. 主从复制的bug 解决方案有两种!****

(1) 隔离级别设为可重复读(Repeatable Read),在该隔离级别下引入间隙锁。当Session 1执行delete语句时,会锁住间隙。那么,Ssession 2执行插入语句就会阻塞住!
(2)将binglog的格式修改为row格式,此时是基于行的复制,自然就不会出现sql执行顺序不一样的问题!奈何这个格式在mysql5.1版本开始才引入。因此由于历史原因,mysql将默认的隔离级别设为可重复读(Repeatable Read),保证主从复制不出问题!

 

3. 为什么大家 将隔离级别设为 读已提交(Read Commited)****

首先排除两种极端方式:读未提交(Read UnCommitted)和串行化(Serializable)两个隔离级别,一个是级别太低,一个是性能太差

 

为了便于描述,下面将

· 可重复读(Repeatable Read),简称为RR;

· 读已提交(Read Commited),简称为RC;

缘由一:在RR隔离级别下,存在间隙锁,导致出现死锁的几率比RC大的多!

缘由二:在RR隔离级别下,条件列未命中索引会锁表!而在RC隔离级别下,只锁行

缘由三:在RC隔离级别下,半一致性读(semi-consistent)特性增加了update操作的并发性!

在5.1.15的时候,innodb引入了一个概念叫做“semi-consistent”,减少了更新同一行记录时的冲突,减少锁等待。

所谓半一致性读就是,一个update语句,如果读到一行已经加锁的记录,此时InnoDB返回记录最近提交的版本,由MySQL上层判断此版本是否满足update的where条件。若满足(需要更新),则MySQL会重新发起一次读操作,此时会读取行的最新版本(并加锁)!

而在RR隔离级别下,Session2只能等待!  

4. 总结:****

两个疑问

在RC级别下,不可重复读问题需要解决么?
不用解决,这个问题是可以接受的!毕竟你数据都已经提交了,读出来本身就没有太大问题!Oracle的默认隔离级别就是RC,你们改过Oracle的默认隔离级别么?

在RC级别下,主从复制用什么binlog格式?
OK,在该隔离级别下,用的binlog为row格式,是基于行的复制!Innodb的创始人也是建议binlog使用该格式!