分享好友 站长动态首页 网站导航

一文详解幻读、脏读和不可重复读

2022-05-04 08:00 · 头闻号数据库

一、简介

经常有面试官提出这么一个问题:什么是脏读、不可重复读和幻读?

关于这个问题,我们还得从数据库的管理系统说起,当数据库管理系统在写入或者更新数据的过程中,为了保证数据是正确可靠的,需要满足四个特性:原子性、一致性、隔离性和持久性,简称 ACID !

例如以银行转账为例,从原账户扣除金额,以及向目标账户添加金额,这两个阶段的操作,被视为一个完整的逻辑过程,不可拆分,简单的说,要么全部成功,要么全部失败!这个过程被称为一个事务,具有 ACID 四个特点!

说了这么多,跟我们今天要说的脏读、不可重复读和幻读有什么关系呢?

我们都知道,当下主流的数据库,都支持多个事务并发执行,当一个事务在写入数据,另一个事务也要读这条数据,会出现哪些问题?当一个事务在写入数据,另一个事务也要写入这条数据,又会发生什么哪些问题?

当多个事务并发处理同一条数据时,如果事务隔离性不合理,就会产生我们今天要介绍的内容,具体的说就是:脏读、不可重复读和幻读!

在事务的四个特性里面,其中隔离性总共分为四种级别:由低到高依次为 Read uncommitted 、Read committed 、Repeatable read 、Serializable ,这四个级别可以逐个解决脏读 、不可重复读 、幻读等这几类问题。

不同的隔离级别,产生的结果是不一样,下面我们一起来具体分析分析!

二、场景分析

2.1脏读

所谓的脏读,指的是读到了其他事务未提交的数据,未提交意味着这些数据可能会保存到数据库,也可能会回滚,不保存到数据库。当这个数据发生了回滚,就意味着这个数据不存在,这就是脏读!

脏读最大的问题就是可能会读到不存在的数据。比如在上图中,事务 B 的更新数据被事务 A 读取,但是事务 B 回滚了,更新数据全部还原。也就是说事务 A 刚刚读到的数据并没有存在于数据库中。

从结果上看,事务 A 读出了一条不存在的数据,这个问题比较很严重!

当数据库的事务隔离级别为读未提交,就会发生脏读现象!

2.2不可重复读

不可重复读,指的是在一个事务内,最开始读到的数据和事务结束前的任意时刻读到的同一批数据出现不一致的情况。

比如上图,事务 A 两次读取同一数据,第一次读取结果为 1,当事务 B 修改了数据并提交,此时的事务 A 第二次读取结果为 2,两次读取结果不一致!

当数据库的事务隔离级别为读未提交、读提交时,就会发生不可重复读现象!

2.3幻读

幻读和不可重复读,有点类似,但是表达的侧重点不一样。

例如事务 A 对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。此时,突然事务 B 插入了一条数据并提交了,当事务 A 提交了修改数据操作之后,再次读取全部数据,结果发现还有一条数据未更新,给人感觉好像产生了幻觉一样。这就是幻读!

当有别的事务,在插入或者删除同一条数据的时候,就容易产生幻读的现象!

当数据库的事务隔离级别为读未提交、读提交、可重复读时,就会发生幻读现象!

三、如何解决

为了解决上述问题,数据库通过锁机制来解决并发访问的问题。

以 Mysql 为例,根据锁定对象不同,分为:行级锁和表级锁;根据并发事务锁定的关系上看,分为:共享锁定和独占锁定。

共享锁定会防止独占锁定,但允许其他的共享锁定;而独占锁定既防止共享锁定也能防止其他独占锁定;为了更改数据,数据库在进行更改的行上施加了行级独占锁定,insert、update、delete和selsct for update语句都会隐式采用必要的行锁定,当冲突加剧,会上升到表级锁定,此时会影响到其他表的访问操作。

直接使用锁机制管理是很复杂的,基于锁机制,数据库给用户提供了不同的事务隔离级别,只要设置了事务隔离级别,数据库就会分析事务中的 sql 语句然后自动选择合适的锁,可以依次有效的解决脏读、不可重复读和幻读问题!

整体的来说,事务的隔离级别和数据库并发性是成反比的,隔离级别越高,并发性越低。

四、小结

本位主要围绕什么是脏读、不可重复读和幻读,进行了简单的介绍,如果有些地方理解不到位,欢迎网友指出!

五、参考

1.程序员那点事 - 一文详解脏读、不可重复读、幻读

2.数据库事务隔离级别

免责声明:本平台仅供信息发布交流之途,请谨慎判断信息真伪。如遇虚假诈骗信息,请立即举报

举报
反对 0
打赏 0
更多相关文章

评论

0

收藏

点赞