MySQL数据库的默认隔离级别为什么是可重复读

落日映苍穹つ 2023-10-06 16:19 112阅读 0赞

一.基本概念

1. mysql的事务隔离级别有哪些?

1.Read Uncommitted(读取未提交内容) 未提交读
2.Read Committed(读取提交内容) 已提交读
3.Repeatable Read(可重读) 可重复读
4.Serializable(可串行化) 可串行化

spring的事务隔离级别 也是这四种. 它默认数据库是什么级别,自己就是什么级别.

2. 什么是脏读 不可重复读 幻读
  1. 1 脏读:AB两事务,A事务会读取到B事务未提交的数据,然后B因为某些原因回滚数据,
  2. 所以A就读取了B没有提交的数据,也称脏数据。
  3. 2 不可重复读:在A事务中对同一数据两次查询不一致,可能原因是在A事务提交
  4. 之前B事务对该数据进行了操作
  5. 3 幻读:类似于不可重复读,都是在一个事务周期内读的数据不一致,
  6. 区别在于幻读是侧重于插入操作带来的影响,而不可重复读是编辑或者删除带来的影响

小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表

3.mysql 事务隔离级别每个解决了什么问题



































隔离级别 脏读 不可重复读 幻读
未提交读
提交读
可重复读
串行化

总结:
未提交读 : 可能发生 脏读 幻读 不可重复读的情况
提交读: 提交读解决了脏读的问题, 但会发生 不可重复读 幻读
可重复读: 解决脏读 不可重复读的问题,但是会发生 幻读
串行化: 解决了这些问题

二. MySQL数据库的默认隔离级别为什么是可重复读

一般的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),保证主从复制不出问题。

发表评论

表情:
评论列表 (有 0 条评论,112人围观)

还没有评论,来说两句吧...

相关阅读