事务的隔离级别介绍

什么是事务?

事务通常就是指数据库事务。事务具有 ACID 特性,即原子性、一致性、隔离性和持久性。

原子性(Atomicity):

事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。
一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束。

隔离性(Isolation):

多个事务并发执行时,一个事务的执行不应影响其他事务的执行。

持久性(Durability):

一个事务一旦提交,他对数据库的修改应该永久保存在数据库中。
SQL-92 标准定义了 4 种隔离级别:读未提交 (READ UNCOMMITTED)、读已提交 (READ COMMITTED)、可重复读 (REPEATABLE READ)、串行化 (SERIALIZABLE)。详见下表:
在这里插入图片描述

Fuzzy Read:

不可重复读: 一个事务中前后两次读取同一个记录,读取的结果不相同。主要针对update操作,一个事务在更新过程中,其它事务更新并提交成功。

Phantom:幻读:

主要针对insert操作操作。一个事务在更新记录,另一个事务插入新的记录,看上去前一个事务没有生效。

Read uncommitted

读未提交,顾名思义,就是一个事务可以读取另一个未提交事务的数据。

读未提交隔离级别是最低的隔离级别。事务没有做任何的隔离措施,会导致Dirty Read,Fuzzy Read,Phantom等问题。

Read Commmited

读提交,顾名思义,就是一个事务要等另一个事务提交后才能读取数据。

Read Commited解决了Dirty Read的问题,不会读到别的事务的中间修改结果。

Read Commited隔离级别解决不了Fuzzy Read的问题:一个事务在处理过程中如果重复读取某一个数据,而且这个数据恰好被其他事务修改并提交了,那么当前重复读取数据的事务就会出现同一个数据前后不同的情况。

例如:事务A和事务B
在这里插入图片描述

图1
如上图1所示,事务TA和TB两个事务:事务TA在t3时刻读到的X的值为1,t4时刻事务TB修改了x为2,并在t5时刻提交了,事务TA在t6时刻读到的x的值为3,导致在事务TA中的两个时刻t3和t6两个时刻读取到的x值不同,就会导致Fuzzy Read不可重复读的问题。

Repeatable read

Repeatable Read重复读隔离级别,简称RR级别隔离。顾名思义,Repeatable Read解决了Fuzzy Read 的问题。

RR级别隔离可以理解为:一个事务一旦开始,事务过程中所读取的所有数据不允许被其他事务修改。

RR隔离一般的实现基于MVCC实现,也称为快照隔离级别。

这个隔离级别没有办法解决“幻影读”的问题。因为它只“保护”了它读取的数据不被修改,但是其他数据会被修改。如果其他数据被修改后恰好满足了当前事务的过滤条件(where语句),那么就会发生“幻影读”的情况。

写偏斜

快照隔离中发生的异常称为“写入偏斜”。

Write skew is possible at this isolation level, a phenomenon where two writes are allowed to the same column(s) in a table by two different writers (who have previously read the columns they are updating), resulting in the column having data that is a mix of the two transactions.

典型示例如下所示:
考虑两个事务P和Q。P将寄存器x中的值复制到y,Q将寄存器中的值从y复制到x。只要两个串行执行:P,Q或者Q,P。无论哪种方式,最终结果都是x = y。但是,快照隔离允许另一个结果:

事务P读取x
事务Q读取y
事务P将其读取的值写入y
事务Q将其读取的值写入x
这在“快照隔离”中是可以有效的发生:每个事务维护数据库的一致视图,并且其写集与任何并发事务的写集不重叠。但是其实x和y已被交换,这两种串行执行都无法实现结果。
Serializable
Serializable 是最高的事务隔离级别,在该级别下,系统中所有的事务以串行地方式逐个执行,能避免所有数据不一致情况,可以避免脏读、不可重复读与幻读。

但是这种以排他方式来控制并发事务,串行化执行方式会导致事务排队,系统的并发量大幅下降,使用的时候要绝对慎重。

真实串行执行
真实串行执行
正如名称所述,不搞花里胡哨,解决并发问题的最好方法就是不并发。这并不是说笑。诸如Redis,VoltDB都采用了单线程执行事务,这可以避免锁开销。

Redis事务的问题:

只能局限在单节点,分布式事务很难实现。事务不能执行时间过长,否则全局阻塞其他事务。

可串行化快照隔离

也叫作SSI(Serializable Snapshot Isolation,可串行化快照隔离)。基于MVCC的两阶段提交(two phrase lock)实现。多版本实现了多个事务的并发更新同一个对象而不用加锁。

乐观事务

乐观事务的假设的前提是:并发事务的冲突比较少,不会产生大量的事务冲突。

乐观事务在提交时检测事务是否冲突,如果有冲突,其中一个事务就需要abort,并重试。

冲突检测主要分为两种情况,即:

检测写以后,先前读的条件是否改变
检测写是否影响了以前的读

悲观事务

悲观事务的假设:并发事务有大量的冲突,通过乐观事务的冲突检测,事务abort,事务重试会导致性能急剧下降。这时候就只能通过lock机制:

具体如下:

事务A读取某个对象,需要给对象加读锁。事务B想要写入,必须等待事务A完成或终止释放读锁。
事务A已经修改某个对象,需要对该对象加写锁,事务B想要读取,必须等待事务A提交或终止以后释放写锁
悲观与乐观的两种方式显然适用于请求较多和请求较少的情况,但毋庸置疑的是它们都突破了单CPU的限制.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值