第五篇:并发控制-隔离

目录

 

回忆

隔离概念——I in ACID

可能的依赖关系

我们如何找到依赖关系?

依赖模型

依赖的正式定义

依赖关系

依赖关系 - 等价

隔离的历史

授予锁或不授予

隔离概念。。

隔离程度


回忆

• 多个并发事务可能会出现问题
• 需要并发控制
     - 独享共享资源,处理并发问题

在本篇内容中,我们将更正式、更详细地了解并发控制

隔离概念——I in ACID

隔离确保并发事务使数据库处于与单独执行事务相同的状态。

隔离保证一致性,前提是每个事务本身都是一致的。

我们可以通过顺序处理每个事务来实现隔离——通常效率不高并且响应时间很短。
我们需要与以下目标同时运行事务:

• 并发执行不应导致应用程序(事务)发生故障。
• 并发执行的吞吐量或响应时间不应低于串行执行。

为了实现隔离,我们需要了解操作的依赖性.

可能的依赖关系

更新丢失脏读不可重复读

T1: Read(o)

T2: Write(o,1)

T1: Write(o,2)

 

T1: Write(o,1)

T2: Read(o)

T1: Write(o,2)

T1: Read(o)

T2: Write(o,1)

T1: Read(o)

我们如何找到依赖关系?

给定一组事务,我们如何确定哪个事务依赖于哪个其他事务?

依赖模型

I_{i}:事务 Ti 的一组输入(读取的对象)
O_{i}:交易 Ti 的一组输出(被修改的对象)
注意 Oj 和 Ij 不一定不相交,即 Oj ∩ Ij ≠ empty

给定一组事务 𝜏 ,事务 Tj 不依赖于 𝜏 中的任何事务Ti,如果 -

O_{i}\cap(I_{j}\cup O_{j}) = empty\: for\:all\: i\neq j

这种方法不能提前计划,因为在许多情况下,输入和输出可能取决于状态/之前不知道。

如果并发事务的输入和输出不是不相交的,则可能会出现以下依赖关系(针对于同一对象):

1、T1 读, T2 写

2、T1 写, T2 读

3、 T1写,T2写

读-读依赖不影响隔离

当依赖图有循环时,就会违反隔离性和不一致的可能性。

依赖的正式定义

令 H 是形式为 (T, action, object) 的元组的历史序列。
设 T1 和 T2 是 H 中的事务。如果 T1 对对象 O 执行一个操作,那么 T2 对同一个 O 执行一个操作,并且在 O 上的另一个事务之间没有写操作——那么 T2 依赖于 T1。

形式上,如果存在索引 i 和 j 使得 i < j, H[i] 涉及 T1 对 O 的动作 a1,(即 H[i ] = (T1,a1,O)) 并且 H[j] 涉及 T2 对 O 的动作 a2(即,H(j) = (T2, a2,O))并且没有其他 H[k] = (T ',WRITE,O) 对于 i < k < j, 则 T2 对 T1 (T1, O, T2) 的依赖性存在于历史 H 中。

依赖图:事务是节点,如果 (Ti, O, Tj) 在 DEP(H) 中,则对象标记从节点 Ti 到 Tj 的边。

依赖关系

我们关注三种场景的依赖
• a1 = 写入 & a2 = 写入;
• a1 = 写 & a2 = 读;
• a1 = READ & a2 = WRITE(依赖于T1 可能在a2 之后再次读取)。

依赖关系 - 等价

DEP(H) = { (Ti, O, Tj) | Tj 依赖于于 Ti }。
给定两个历史 H1 和 H2 包含相同的元组,如果 DEP(H1) = DEP(H2),H1 和 H2 是等价的

这意味着通过执行 H1 或 H2 中的操作序列之一,给定的数据库将最终处于完全相同的最终状态

隔离的历史

如果一个历史相当于一个串行历史(就好像所有事务都是串行/顺序执行的),那么它被称为是隔离的
串行历史是由于一个接一个地顺序运行事务而产生的历史。 N 个事务最多可以产生 N 个! 连载历史。

如果 T1 在 T2 之前,
写成 T1 << T2。
Before(T)= {T' | T’<<T}
After(T)= {T'| T<<T'}

交易 T' 被称为虫洞事务,如果

T^{'}\in Before(T)\cap After(T)

即 T << T' << T。这意味着在历史的依赖图中存在一个循环。 虫洞事务的存在意味着它不是孤立的(=> 不是串行调度)。

一个历史是连续的,如果它一次连续运行一个事务,或者相当于一个连续的历史。
连续历史是孤立的历史。
虫洞定理:一段历史是孤立的,当且仅当它没有虫洞。

我们现在将介绍一种新型锁——
SLOCK(共享锁)允许其他事务读取,但不允许 写入/修改共享资源

虫洞事务的概念在后面的话题中会有用!

授予锁或不授予

当一个对象被另一个事务以不兼容的模式锁定时,不应将对该对象的锁定授予一个事务。

锁兼容性矩阵
 锁定模式
当前模式Free共享独占
共享请求 (SLOCK) 用于阻止其他人写入/修改兼容的
立即批准请求
将模式从免费更改为共享
兼容的
立即批准请求
模式保持共享
冲突
请求延迟,直到状态变得兼容
模式保持独占
独占请求 (XLOCK) 用于阻止其他人读取或写入/修改兼容的
立即批准请求
将模式从免费更改为独占
冲突
请求延迟,直到状态变得兼容
模式保持共享
冲突
请求延迟,直到状态变得兼容
模式保持独占

隔离概念。。

事务中的操作有:READ、WRITE、XLOCK、SLOCK、UNLOCK、BEGIN、COMMIT、ROLLBACK

BEGIN、END、SLOCK、XLOCK 可以忽略,因为它们可以根据相应的操作自动插入

例如。 如果事务以 COMMIT 结束,则替换为:{UNLOCK A if SLOCK A 或 XLOCK A 出现在 T 中的任何对象 A}。 (也就是简单的释放所有的锁)

类似地,ROLLBACK 可以替换为 {WRITE(UNDO) A,如果 WRITE A 出现在 T 中的任何对象 A} { UNLOCK A 如果 SLOCK A 或 XLOCK A 出现在 T 中的任何对象 A}。

格式良好的事务:如果所有的 READ、WRITE 和 UNLOCK 操作都被适当的 LOCK 操作覆盖,那么一个事务就是格式良好的
两阶段事务:如果所有 LOCK 操作先于其所有 UNLOCK 操作,则事务是两阶段的。

概括:
事务是对以 COMMIT 或 ROLLBACK 结尾的对象的一系列 READ、WRITE、SLOCK、XLOCK 操作。
如果每个 READ、WRITE 和 UNLOCK 操作都更早地被相应的锁定操作覆盖,那么事务就是结构良好的。
如果不授予冲突授权,历史记录是合法的。
如果事务的所有锁定操作都先于其解锁操作,则该事务是两阶段的。

锁定定理:如果所有事务都是良构的(READ、WRITE 和 UNLOCK 操作较早被相应的锁定操作覆盖)并且
两阶段(锁只在最后释放),那么任何合法的(不授予冲突的授予)历史将被隔离。
锁定定理(Converse):如果一个事务没有很好地形成或不是两阶段的,那么有可能写另一个事务,使其成为虫洞。
回滚定理:执行 UNLOCK 然后执行 ROLLBACK 的更新事务不是两个阶段。

隔离程度

程度3:程度三隔离事务没有丢失更新,并且具有可重复读取。 这是“真正的”隔离。

锁定协议是两阶段的并且格式良好
它对以下冲突很敏感:
写->写; 写->读; 读->写

程度2:程度2隔离事务没有丢失更新和脏读。

锁协议在排他锁方面是两阶段并且在读和写方面格式良好。 (可能有不可重复的读取。)

也就是说并没有保证两段锁,只保证了格式良好,如下图
它对以下冲突很敏感:
写->写; 写->读;

程度1:程度1隔离没有丢失更新。

锁协议在排他锁方面是两个阶段,在写方面是良好的

也就是这里面只保证了两段锁,如下图
以下冲突是敏感的:
写->写;

程度 0 :如果另一个事务至少是程度1,则程度0事务不会覆盖另一个事务的脏数据。

锁定协议在写入方面格式良好。如下图
它忽略所有冲突。

ok,今天关于并发控制,隔离相关概念就说到这里了,欢迎大家随时评论区交流哦!辛苦大家了,谢谢!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值