典型的DBMS系统默认使用读取提交(RC ) (如Oracle和SQLServer )作为默认隔离级别,而MySQL使用可读) RR )。 要知道隔离级别越高,可以解决的数据一致性问题就越多,理论上性能损失越大,并发性也越差。 隔离级别是序列化RR RC读取未提交的顺序
在SQL标准中,前三个隔离级别分别解决了重影读取、不可重复读取和脏读问题。 那么,为什么MySQL使用可重复读取作为缺省隔离级别呢?
这是有历史理由的。 从主从副本开始吧。
1 .主从副本是根据什么复制的?
已基于binlog复制
2.binlog有几种格式?
statement:记录SQL语句的更改
row :记录了每行中执行数据的更改
混合:语句和行模式混合
那Mysql在5.0之前的版本中,binlog只支持语句格式! 在此格式中,Mysql将“读取提交”(Read Commited )作为默认隔离级别,因为主从副本中存在错误!
接下来,我们将讨论如果binlog采用语句格式,隔离级别为“读取提交”(Read Commited ),则存在哪些错误。 如下图所示,在主(主)上执行以下事务:
此时在主库中查询:
选择*从t;
输出结果:
---|C1|C2---|2--------2|2-----------------1行插入
从库咨询:
选择*从t;
输出结果:
Empty set
这里发生了主从不匹配的问题! 理由很简单,因为在master中执行的顺序先删除后插入! 在这种情况下,binlog是语句格式,记录的顺序是先插入,然后删除! 从(从属)同步的是binglog,因此从属执行的顺序和主机不匹配! 出现的主绝不一致!
怎么解决?
解决方案有两种!
(1)使隔离级别为可反复读取(Repeatable Read ),在该隔离级别导入间隙锁定。 当Session 1执行delete语句时,间隙将被锁定。 那么,Ssession 2执行插入语句时将被阻止!
)2)将binglog格式更改为row格式。 此时是基于行的副本,所以当然不会出现sql执行顺序不同的问题。 这种无可救药的格式是从MySQL 5.1版引入的。因此由于历史原因,mysql将默认的隔离级别设为可重复读(Repeatable Read),保证主从复制不出问题!