栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

数据库并发问题及四种隔离级别原理深入分析(最详细)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

数据库并发问题及四种隔离级别原理深入分析(最详细)

目前网上绝大部分文章只说了并发存在的问题以及隔离级别有哪些,很少有深入分析其具体的实现原理的,本文以最简单实例总结一下。


引言

数据库中事务要遵循的ACID特性:

  • 原子性(Atomicity)
  • 一致性(Consistensy)
  • 隔离性(Isolation)
  • 持久性(Duration)

其中隔离性体现的就是多个事务并发操作数据库时,应该是独立互不干扰的。实际情况中,隔离性是比较灵活的,设定了多个分层级别,主要是为了应对事务并发操作数据库时带来的几个常见问题。


并发常见问题

通常所说的并发问题包括脏读、不可重复读、幻读,这里把脏写也算上,其实和脏读是一类情况。

用两个事务的执行来举例,直观理解。

1 脏读
事务A事务B
UPDATe users SET age = 21 WHERe id = 1;

SELECT age FROM users WHERe id = 1;

ROLLBACK

事务B修改了表中某行的值,但未提交。此时事务A来了读取到了该行被事务B修改后的值,过一会事务B又回滚了。则事务A读取到的值为脏数据,用该数据做的一切操作在回滚后都无效了。

由于读到的数据不是真正写入数据库的,因此称为脏读。

2 脏写
事务A事务B
UPDATe users SET age = 21 WHERe id = 1;

SELECT age FROM users WHERe id = 1
UPDATe users SET age = 22 WHERe id = 1;

ROLLBACK

在脏读的基础上,事务A读取到脏数据后,对脏数据又进行了修改。等到事务B回滚后,这个修改也无效了。

由于写入的这个数据是无效的,因此称为脏写。

注意:脏写可归到脏读中,事务A读取到脏数据后的一系列操作可包括脏写。

3 不可重复读
事务A事务B
SELECT age FROM users WHERe id = 1

UPDATe users SET age = 21 WHERe id = 1;
COMMIT
SELECT age FROM users WHERe id = 1

事务A先读取了表中某行的值,此时事务A还未结束。之后事务B来了修改了该值并且提交了,事务A一会又读了一遍该行值,发现前后不一样了。

由于从数据一致性的角度可以说该行值不可重复读,因此称为不可重复读

4 幻读
事务A事务B
SELECt * FROM users WHERe age BETWEEN 10 AND 30;

INSERT INTO users VALUES ( 3, ‘Bob’, 27 );

COMMIT
SELECt * FROM users WHERe age BETWEEN 10 AND 30;

事务A先查询了一些数据,此时事务A还未结束。事务B来了,插入了一些数据,然后事务A再按之前的条件查询了一次,发现查到的数据变多了。

由于站在事务A的角度看凭空多了一些数据,像幻象一样,因此成为幻读。


四种隔离级别实现原理

为了应对上述并发问题,InnoDB中设置四种隔离级别(Myisam不支持事务):

  • 未提交读——READ UNCOMMITED,解决脏写
  • 已提交读——READ COMMITED,解决脏读
  • 可重复读——REPEATABLE READ,解决脏读、不可重复读
  • 串行化——SERIALIZABLE,解决脏读、不可重复读、幻读

首先明确,隔离级别的实现均通过行级锁和表级锁来实现!

三种隔离级别依次解决每一个并发问题,下面层层递进分析每一种隔离级别的实现原理。

1 未提交读

未提交读是最松的一种并发策略,存在脏读、可重复读、幻读的问题。

原理:
事务在读数据时,不加任何锁
事务在写数据时,对数据加行级共享锁,事务结束时释放

2 已提交读

已提交读可以解决脏读问题,但还存在可重复读、幻读的问题。

原理:
事务在读数据时的瞬间加行级共享锁,读完马上释放
事务在写数据时,只对数据加行级排他锁,事务结束时释放

如何解决脏读?
为了解决脏读的问题,要保证事务A在事务B修改数据并且提交之后才能读,因此与未提交读的区别在于:在写数据时要加行级排他锁,使得事务B从修改数据开始一直到事务结束时都不会被事务A读取被修改数据

3 可重复读

可重复读可以解决脏读、不可重复读问题,但还存在幻读的问题。

原理:
事务在读数据时,对数据加行级共享锁,事务结束时释放
事务在写数据时,对数据加行级排他锁,事务结束时释放

如何解决不可重复读?
为了解决不可重复读的问题,要保证事务A在读数据后到事务结束这个过程中事务B不能对其进行修改,因此与已提交读的区别在于:读数据时加行级共享锁,一直到事务结束再释放而不是读完就释放

4 串行化

串行化可以解决脏读、不可重复读、幻读问题,所有问题都解决,但并发度最低

原理:
事务在读数据时,对数据加表级共享锁,事务结束时释放
事务在写数据时,对数据加表级排他锁,事务结束时释放

如何解决幻读?
为了解决幻读的问题,要保证事务A在读数据后到事务结束这个过程中事务B不能插入数据,因此与可重复读的区别在于:把锁换成表级的,事务A对某个表中数据操作时,事务B不能再操作这个表

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/571979.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号