一般的DBMS系统,默认城市利用读提交(Read-Comitted,RC)作为默认断绝级别,如Oracle、SQLServer等,而MySQL却利用可反复读(Read-Repeatable,RR)。要知道,越高的断绝级别,能办理的数据一致性问题越多,理论上机能损耗更大,可并发性越低。断绝级别依次为>:串行化 > RR > RC >读未提交
在SQL尺度中,前三种断绝级别别离办理了幻象读、不行反复读和脏读的问题。那么,为什么MySQL利用可反复读作为默认断绝级别呢?
这个是有汗青原因的,要从主从复制开始讲起了!
1.主从复制,是基于什么复制的?
是基于binlog复制的
2.binlog有几种名目?
statement:记录的是修改SQL语句
row:记录的是每行实际数据的改观
mixed:statement和row模式的殽杂
那Mysql在5.0这个版本以前,binlog只支持STATEMENT这种名目!而这种名目在读已提交(Read Commited)这个断绝级别下主从复制是有bug的,因此Mysql将可反复读(Repeatable Read)作为默认的断绝级别!
接下来,就要说说当binlog为STATEMENT名目,且断绝级别为读已提交(Read Commited)时,有什么bug呢?如下图所示,在主(master)上执行如下事务:
此时在主库中查询:
select * from t;
输出功效:
+---+---+ | c1 |c2 +---+---+ | 2 | 2 +---+---+ 1 row in set
从库中查询:
select * from t;
输出功效:
Empty set
这里呈现了主从纷歧致性的问题!原因其实很简朴,就是在master上执行的顺序为先删后插!而此时binlog为STATEMENT名目,它记录的顺序为先插后删!从(slave)同步的是binglog,因此从机执行的顺序和主机纷歧致!就会呈现主从纷歧致!
如何办理?
办理方案有两种!
(1)断绝级别设为可反复读(Repeatable Read),在该断绝级别下引入间隙锁。当Session 1执行delete语句时,会锁住间隙。那么,Ssession 2执行插入语句就会阻塞住!
(2)将binglog的名目修改为row名目,此时是基于行的复制,自然就不会呈现sql执行顺序纷歧样的问题!怎样这个名目在mysql5.1版本开始才引入。
因此由于汗青原因,mysql将默认的断绝级别设为可反复读(Repeatable Read),担保主从复制不出问题。