深入理解数据库事务隔离级别--Mysql默认选择可重复读

为什么Mysql默认选择可重复读


Mysql主从复制,是基于binlog复制的;而binlog是一个记录数据库更改日志文件.
binlog有三种格式,分别是

  • statement:记录的是修改SQL语句
  • row:记录的是每行实际数据的变更
  • mixed:statement和row模式的混合

Mysql5.0版本以前,binlog只支持STATEMENT这种格式!而这种格式在读已提交(Read Commited)隔离级别下,主从复制是有bug的,因此Mysql将可重复读作为默认的隔离级别。
当binlog格式为STATEMENT,且隔离级别为读已提交时,有什么bug呢?如下图所示,在主(master)上执行如下事务
深入理解数据库事务隔离级别--Mysql默认选择可重复读_第1张图片
此时在主(master)上执行下列语句

select * from test;

输出如下

+---+
| b |
+---+
| 3 |
+---+
1 row in set

但是,你在此时在从(slave)上执行该语句,得出输出如下

Empty set

出现了主从不一致性的问题!原因其实很简单,就是在master上执行的顺序为先删后插!而此时binlog为STATEMENT格式,它记录的顺序为先插后删!从(slave)同步的是binglog,因此从机执行的顺序和主机不一致!就会出现主从不一致!
如何解决?
解决方案有两种!
(1)隔离级别设为可重复读(Repeatable Read),在该隔离级别下引入间隙锁。当Session 1执行delete语句时,会锁住间隙。那么,Ssession 2执行插入语句就会阻塞住!
(2)将binglog的格式修改为row格式,此时是基于行的复制,自然就不会出现sql执行顺序不一样的问题!奈何这个格式在mysql5.1版本开始才引入。因此由于历史原因,mysql将默认的隔离级别设为可重复读(Repeatable Read),保证主从复制不出问题!

那么,当我们了解完mysql选可重复读(Repeatable Read)作为默认隔离级别的原因后,接下来我们将其和读已提交(Read Commited)进行对比,来说明为什么在互联网项目为什么将隔离级别设为读已提交(Read Commited)

你可能感兴趣的:(数据库,Mysql事务默认隔离级别)