首页 > 编程知识 正文

四种隔离级别由低到高,数据库默认的隔离级别

时间:2023-05-05 05:19:20 阅读:26887 作者:4908

的事务隔离级别是关系数据库事务的理论基础,本文从资源互斥的角度从上到下依次进行说明。

1 .数据库事务隔离级别1.1事务隔离级别,隔离的是什么?

在说明数据库事务的隔离级别时,首先必须清楚这隔离到底隔离了什么。

什么是事务?

从数据库的事务定义来看,它具有ACID特性(即,原子性、一致性一致性、隔离、隔离、持续)

从一般意义上说,事务是指可以在原子上进行,全部成功还是全部失败的隔离性是什么? 被隔离的是什么?隔离性理想情况下,不同的客户端在进行事务操作时,各客户端之间没有相互影响,仿佛无法感知对方的存在。 隔离是指实际上隔离的对象是数据库资源的互斥访问,隔离性通过由数据库资源分类的不同粒度来表示。

其次,本文通过对数据库资源的粒度划分,论述了隔离性不同层次的实现。 1.2 -隔离级别-序列化读取(序列化读取(序列化读取) ) ) ) ) ) ) ) ) ) )。

1.1.1将整个数据库作为排他资源

假设整个数据库都是对互斥资源的访问,则此访问具有以下特性:

一次只能连接到数据库进行事务处理操作的一个客户端,在该客户端完成事务处理之前,其他客户端不能对数据库执行事务处理操作。

当客户端访问数据库时,每个客户端都以互斥方式访问。 交互如下图所示。

这种隔离级别的理想情况是,不同的客户端事务不会相应地产生影响。 之所以这么说,是因为所有客户端都是在事务操作时排队的。

数据库除了在理论上的严谨性之外,还要看它的实用性。以下是衡量数据库性能的标准之一。 TPS越高,TPS:“每单位时间的事务数”(Transactions Per Second )表示数据库性能越高。在后续的介绍中,将会使用这一指标来衡量每一个隔离级别的性能。

假设每个客户端的事务操作需要t秒钟,并且在此期间没有空闲,则数据库的最大TPS能力为1/T。

最大TPS=1/t(t (其中t是客户端的平均事务处理操作时间) )。

例如,如果T=10ms,则数据库此时的TPS值为1/0.01=100,数据库每秒可以完成100个事务操作

合理性讨论:使用数据库级别作为互斥资源,有这么必要吗?

使用数据库级作为互斥资源访问可以完全保证事务的隔离性,但在实际应用场景中,不需要使用这种粗粒度的互斥资源。

例如,假设数据库mall中有两个表: t_user和t_order。 外部有四个客户端a、b、c和d。 其中,a客户端和b客户端只操作了t_user表,c客户端和d客户端只操作了t_order表。

从互斥资源的角度看,客户端访问互斥资源时,分别有at _ userb、ct _ orderd两组互斥资源,在进行事务隔离控制时,将数据库作为互斥资源您可以将互斥资源细分为表级别。

1.1.2使用数据库中的表作为独占资源

在上面的示例中,数据库中的表是互斥资源,细分的交互如下

如果将锁定级别设置为表级别,则在时间序列操作中有两个资源互斥组t_user-[A,B]、t_order-[C,D],这两个互斥组之间可以并行处理,而不会相互影响并行处理的结果如下图所示。

通过将资源的独占级别从数据库级别细分为表级别,数据库的TPS数量也有了相当大的提高。 现在,让我们简单估算一下满负荷状态下的TPS。 或者,假设客户机的平均事务处理时间为t,资源排他组数为n,则:

最大TPS=(1/t ) n

在本例中,在T=10ms、N=2的情况下,TPS=(1/0.01 ) * 2=200

与将数据库作为独占资源相比,可以看到TPS也有所提高,以便独占粒度降低到表级别。

注意:在真实的事务操作中,可能一个客户端事务会操作多张表,那这多张表的任意一张表都会被当做互斥资源

当前主流数据库的实现基本上是以锁定表的方式提供资源独占资源访问,锁定所有表的方式的事务隔离处理在操作时刻进行队列性质的提升,该事务隔离的级别为http://www.sinsing序列化读(SERIALIZABLE READ)

我们可以简单地来理解序列化读的实现方式:锁全表中,对同一表操作的客户端事务操作是排队序列化操作。 让我们来看看下一个场景:

假设现在有客户端a和客户端b。

在事务操作时,共同使用一张表T_USER,但是他们操作的行信息有所不同:

上图中,虽然客户端A和客户端B 以互斥的方式访问表T_USER,但是操作的数据并没有真正的互斥,那我们可以继续将锁的粒度细化,从锁表这一级,再次细化到锁行记录这一级,这将进一步提高系统的并发处理能力。经过行锁细化后,其隔离级别就降到了可重复读。

1.2 可重复读(REPEATABLE_READ)

将上述的例子展开,通过模型的方式体现,如下图所示:

客户端A和客户端B 同时尝试访问相同的行数据;而客户端C和客户端D也是同时尝试访问相同的行数据。在此竞争过程中,可以看到,最多可以有两个客户端可以同时访问表T_USER,和序列化读相比,整个客户端的并发量又提高了一个量级!

用客户端时序关系表示如下:

看到这个结果,是不是有这样的感觉:哇塞,既然使用行锁并发能力这么高,为什么还要 锁表方式的序列化读(SERIALIZABLE READ)?
解答这个问题之前,我们来看下这种行锁方式有什么问题。
通过行锁的方式,能够锁定客户端锁操作的行;而在事务进行的过程中,可能会往对应的表中插入新的数据,而这个新的数据,起初并不数据锁定范围,使用SQL语句操作数据库数据时,可能会返回更多的满足条件的数据,加入新的行锁,如下图所示:

如上图所示:在同一个事务内,完全相同的两次查询,返回的记录数不一致,好像多读了数据一样,这种情况,称为幻读(Phantom Read)

使用这种行锁的方式进行资源隔离的方式,在数据库隔离级别上被称为 可重复读 (REPEATABLE READ)

注意:虽然使用行锁互斥的方式进行数据库操作,但是会出现幻读的情况,避免幻读的方式,可以使用表级锁—即提高事务的隔离界别—序列化读(SERIALIZABLE READ)

1.3 读已提交(READ_COMMITTED)

实际上,数据库在实现原子性(Atomic)时,对于某一表的特定行,其实有两个状态:Uncommited、Commited,我们将资源在行数据的基础上继续细分,如下图所示:

为了进一步提高数据库的并发能力,如上图所示,将在某一行数据上,使用读写分离锁的机制:客户端B和客户端D直接使用读锁读取数据,读锁是共享锁,所以可以同时进行;而客户端A和客户端C 事务操作上,会存在两个环节:Uncommited—> Commited,在真正 commit的时候,则使用写锁以互斥的方式完成事务,把互斥访问资源的时机压缩的更短。

上述的客户端B和客户端D只读取已提交的数据的方式,在隔离级别中,被称为读已提交(READ_COMMITED).

通过上述的流程,我们的数据库的并发能力又能提高一个量级,一切是多么“美好”!

但是这个只是想象中的美好而已,接下来看它存在的问题。假设我们有如下的数据库操作:

上述的例子中,reader在一个事务中,相同的查询条件,返回的行记录是同一条,但是这一条的记录的AGE列值从18变成19,虽然是相同的行记录,但是内容不一致,这种现象叫做不可重复读(NO-REPEATABLE-READ)。

虽然读已提交(READ COMMITED)隔离级别的并发读能力提高了很多个量级,但是在一个事务内,会造成不可重复读(NO-REPEATABLE-READ)的情况

读已提交的不可重复读现象对开发同学有什么启示?
不可重复读会导致一条行数据两次读取数据可能不一致,这就要求我们在数据库事务操作上,尽可能少用查询出来的结果作为参数执行后续的updateSQL 语句,尽可能使用状态机来保证数据的完整性。这方面的知识可以单独开一个课题来讨论 :如何使用数据库来保证业务数据的逻辑完整性?

1.4 读未提交(READ_UNCOMMITTED)

上述的读已提交(READ_COMMITTED)的本质,是将资源互斥访问的粒度控制到 committed的行数据上,而实际上,还可以继续将资源互斥的访问粒度,细化到未提交(UNCOMMITED)的行数据上,如下图所示:

这种方式,由于更细化了资源锁的粒度,其客户端的并发能力又得到了进一步的提升。但是,与此同时,会存在新的问题—脏读现象,具体流程示例如下图所示:

如上图所示:客户端reader在事务的过程中,读取到了其他客户端updater尚未提交的数据,之后客户端reader 可能将其当做已经持久化的数据进行业务操作,而实际上,客户端updater可能将其数据回退;在此过程中,客户端reader读取的数据就成了脏数据,客户端reader的读数据行为为:脏读(Dirty Read)

1.5 小结

对上述的四种事务隔离级别的阐述中,我们使用了从资源互斥访问的角度做了解释。资源互斥粒度控制的越细,客户端事务的并发能力就越高,但是与此同时,会相应地降低数据的一致性。

事务的并发数和数据数据一致性这两个是两个相反的理想指标。而数据库研发的方向就是尽可能提高同时提高两个指标,尽可能减少之间的反作用影响。

2. 数据库隔离级别和数据一致性的关系

数据库的隔离级别一般分为四个级别,从隔离级别由高到低排序的话,分别是:SERIALIZABLE —> REPEATABLE READ—> READ_COMMITTED —>READ_UNCOMMITED,其分别表示如下几种含义:

SERIALIZABLE 序列化读,隔离级别最高,客户端以互斥的方式访问数据库资源,统一时间内,同一个资源只能被一个客户端访问,好像客户端在排队请求访问,所以称为序列化读。REPEATABLE_READ 可重复读,可重复读能够保证,一个客户端在一个事务内,多次访问同一个资源时,返回结果是一样的,顾名思义,称为可重复读,这种隔离级别可能会造成幻读现象。READ_COMMITTED 读已提交,即客户端在一个事务内,每次查询读取的数据都是从数据库读取最新的已提交的数据;这种隔离界别可能会造成不可重复读和幻读现象。READ_UNCOMMITTED 读未提交,即客户端在一个事务内,可以读取到其他客户端事务的尚未提交的数据;这种隔离级别可能会造成脏读、不可重复读、幻读 现象。

数据库之所以有四种隔离级别,是基于对应的并发能力相关,如下图所示,隔离级别越高,数据库的并发处理能力就越低;反之,隔离级别越低,数据库的并发处理能力就越高

3. 总结

本文通过资源的角度从上到下分析了数据库隔离级别设计的基本理念,以及相应的数据一致性的关系,帮助大家对数据库隔离级别有更清晰的认识。

 

转载地址:https://louluan.blog.csdn.net/article/details/95319795

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。