【数据库】事务管理概念
事务管理概念
- 1.事务简介
- 2.可串行化 Serializability
- 2.1 冲突可串行化(Conflict Serializability)
- 2.2 冲突可串行化的优先图解法(可串行化测试)
- 3.可恢复性
- 3.1 可恢复调度
- 3.2 级联回滚
- 3.3 目标
- 4.一致性控制(Concurrency Control)
- 4.1 Lock-Based Protocols 基于锁的协议
- 4.2 两阶段锁协议(The Two-Phase Locking Protocol)
- 4.3 死锁处理
- 4.4 基于时间戳的协议 Timestamp-Based Protocols
- 5. 恢复系统
- 5.1 事务失败分类
- 5.2 存储结构
- 5.3 数据访问
- 5.4 恢复与原子性
- 5.5 日志
- 5.6 数据库修改
- 5.7 undo和redo
- 定义
- 执行条件
- 5.8 恢复算法(重点)
- 正常操作
- 故障中恢复(Recovery from failure)
- 6.事务隔离级别
- 7.缓冲区管理(期末不考先略,后面补充)
1.事务简介
事务是访问并可能更新各种数据项的程序执行单元。
事务状态:
- 活动(active) ― 初始状态;事务在执行时保持此状态
- 部分提交(partially committed) – 在执行最终语句之后。
- 失败(failed) – 在发现正常执行无法再继续之后。
- 已中止(aborted) – 在事务回滚并将数据库还原到事务开始之前的状态之后。
- restart事务 仅当没有内部逻辑错误时才能完成
- kill事务 它通常是因为一些内部逻辑错误而这样做的。
- 已提交(committed) – 成功完成后。
2.可串行化 Serializability
可串行化分为:1. 冲突可串行化 2. 视图可串行化
这里只介绍冲突可串行化
冲突指令:对同个数据项操作,且调换顺序会影响结果
当I和J是不同事务在相同数据项的操作,且至少有一个是write时,I和J是冲突的
2.1 冲突可串行化(Conflict Serializability)
如果一个调度 S 可以通过一系列不冲突指令的交换转换为调度 S’,我们说 S 和 S’ 是冲突等价(Conflict equivalent)的。
如果计划 S 与一个串行计划冲突等效(不是所有串行调度之间都是冲突等价的),则它是冲突可串行化的
如下面两个事务就是冲突可串行化的
2.2 冲突可串行化的优先图解法(可串行化测试)
可串行化测试有助于我们了解并发控制协议为何是正确的。
考虑一组事务 T1、T2、…、Tn 的某个调度(schedule) ,优先图(precedence graph)是有向图,其中顶点是事务(名称)。如果两个事务发生冲突,我们从 Ti 到 Tj 绘制一条弧线,并且 Ti 访问了之前发生冲突的数据项。
如果优先图无环,在优先图中进行拓扑排序就是串行化后的执行顺序。
解释:
由T1的Read(Y)先于T2的Write(Y),因此T1->T2
由T1的Read(Z)先于T3的Write(Z),因此T1->T3
由T1的Read(Y)先于T4的Write(Y),因此T1->T4
由T2的Write(Y)先于T4的Read(Y),因此T2->T4
由T3的write(Z)先于T4的Read(Z),因此T3->T4
拓扑排序的一个结果T1->T3->T2->T4->T5
3.可恢复性
3.1 可恢复调度
可恢复调度(Recoverable Schedule) — 如果事务 Tj 读取了先前由事务 Ti 写入的数据项,则 Ti 的提交操作出现在 Tj 的提交操作之前。
下图即为不可恢复调度,如果 T8 中止,则 T9 将读取(并可能向用户显示)不一致的数据库状态。 因此,数据库必须确保调度是可恢复的。
3.2 级联回滚
级联回滚(Cascading callback) – 单个事务失败会导致一系列事务回滚。
以下调度,其中尚未提交任何事务(因此调度是可恢复的),但T10异常会导致T11和T12也回滚
无级联调度(Cascadless schedule) — 不会发生级联回滚
对于 Ti 和 Tj 的每对事务,使得 Tj 读取之前由 Ti 写入的数据项,Ti 的提交操作出现在 Tj 的读取操作之前。无级联调度也是可恢复的
3.3 目标
做到并发,并且保证冲突或视图可串行化,以及可恢复,最好是无级联的
4.一致性控制(Concurrency Control)
4.1 Lock-Based Protocols 基于锁的协议
锁是一种控制对数据项的并发访问的机制
数据项可以在两种模式下锁定:
- 独占(X)模式(exclusive mode)。数据项既可以读取,也可以写入。X-lock 是使用 lock-X 指令请求的。
- 共享(S)模式(shared mode)。只能读取数据项。S-lock 是使用 lock-S 指令请求的。 向并发控制管理器发出锁定请求。只有在授予请求后,事务才能继续。
锁兼容性矩阵:只要有一个事务拿了排他锁X,其他任何事务都不能访问该数据项;有一个事务拿了共享锁S,其他事务不能拿排他锁X;没事务拿排他锁X,可以有很多事务同时拿共享锁S
死锁:如果存在一组事务,使得该集合中的每个事务都在等待该集中的另一个事务,则系统处于死锁状态。
一个事务拿了排他锁,但该事务却没释放锁,其他事务又需要拿这个数据项的锁等待该事务释放锁,两个事务都动不了,即为死锁状态,如下图所示,要解决只能回滚
饥饿(starvation):事务可能正在等待某个项目上的 X 锁,而一系列其他事务请求并在同一项目上被授予 S 锁 或者是由于死锁,同一事务被反复回滚。
4.2 两阶段锁协议(The Two-Phase Locking Protocol)
这是一种确保冲突可串行化调度的协议。
第 1 阶段:生长阶段(Growing Phase) 事务可能获得锁 事务可能不会释放锁
第 2 阶段:收缩阶段(Shrinking Phase) 事务可能会释放锁 事务可能无法获取锁
该协议可确保可串行化。可以证明,事务可以按其锁点的顺序(即事务获取其最终锁点的点)串行化,但不能确保无级联回滚,没死锁。
严格两阶段锁协议(strict two-phase locking):事务必须保留其所有排他(exclusive)锁,直到它提交/中止,避免级联回滚
强两阶段锁协议(Rigorous two-phase locking):所有锁都保持到提交/中止。在此协议中,事务可以按其提交的顺序进行串行化。
带锁转换的两阶段锁协议:
- 第一阶段: 可以在项目上获取锁-S 可以在项目上获取锁定-X 可以将锁-S转换为锁X(升级)
- 第二阶段: 可以释放锁-S 可以释放锁-X 可以将锁 X 转换为锁 S(降级)
此协议可确保可串行化。但仍然依靠程序员插入各种锁定指令。
实际当中:
- 碰到Read(Q)就加S锁lock-S(Q)
- 碰到write如果原先有S锁就upgrade到X锁,没有就加lock-X(Q)
- 到了abort或者commit之后就unlock
4.3 死锁处理
两种策略:①死锁预防 ②死锁探测和恢复
- Deadlock prevention死锁预防:
- 要求每个事务在开始之前封锁它的所有数据项(先声明),对所有数据项强加一个次序,事务只能按要求的次序顺序封锁数据项
- 锁超时(lock timeout):事务仅等待锁定指定的时间。之后,事务将回滚。
- 恢复机制(使用抢占preemption和回滚rollbacks):
- wait-die策略(非抢占式):老事务等新事务释放数据项
- wound-die策略(抢占式):强制回滚新事务
- 根据已使用的数据项数,还需要的数据项数、回滚涉及的事务数、已经回滚的次数作为指标选择回滚对象
- 死锁探测
- 等待图:以事务Ti为顶点,Ti指向Tj的有向边代表Ti等待Tj释放数据项,有环时,证明死锁
4.4 基于时间戳的协议 Timestamp-Based Protocols
概念:
- 事务的时间戳代表事务进入系统时的时间
- W-timestamp(Q)表示成功执行write(Q)的所有事务的最大时间戳.
- R-timestamp(Q)表示成功执行read(Q)的所有事务的最大时间戳.
基于时间戳的排序协议可以保证任何有冲突的read和 write 操作按时间戳顺序执行。
假设事务 Ti read(Q):
- 如果 T S ( T i ) < = W t i m e s t a m p ( Q ) TS(Ti) <= Wtimestamp(Q) TS(Ti)<=Wtimestamp(Q),即事务时间戳在Q最后一个写之前,则 Ti 需要读取已覆盖的 Q 值。 因此,读取操作被拒绝,Ti 回滚。
- 如果 T S ( T i ) > = W t i m e s t a m p ( Q ) TS(Ti) >= Wtimestamp(Q) TS(Ti)>=Wtimestamp(Q),即事务时间戳在Q最后一个写之后,则执行read操作,并将R-timestamp(Q) 设置为 m a x ( R t i m e s t a m p ( Q ) , T S ( T i ) ) max(Rtimestamp(Q), TS(Ti)) max(Rtimestamp(Q),TS(Ti))。
- 不需要跟R-timestamp(Q)比较,只要能执行,R-timestamp就能更新
假设事务 Ti write(Q):
- 如果 T S ( T i ) < R t i m e s t a m p ( Q ) TS(Ti)< Rtimestamp(Q) TS(Ti)<Rtimestamp(Q),即事务时间戳在Q最后一个read之前,以前需要Ti产生的Q的值,系统假定永远不会生成该值。 因此,写入操作被拒绝,Ti 回滚。
- 如果 T S ( T i ) < W t i m e s t a m p ( Q ) TS(Ti) < Wtimestamp(Q) TS(Ti)<Wtimestamp(Q),即事务时间戳在Q最后一个write之前,Ti 正在尝试写入过时的 Q 值。 因此,此写入操作将被拒绝,Ti 将回滚。
- 其他情况,执行该操作,并且把Wtimestamp(Q)设置为TS(Ti)
例子:
这里T5 read(Z),事务T5时间戳在T3 read(Z)之前,因此操作被拒绝,T5要回滚。
T2 read(Z) 同理
这里T3 read(W),事务T3时间戳在T4 read(W)之前,因此操作被拒绝,T3要回滚。
……
时间戳协议可确保没有死锁,因为没有事务等待。
但是,调度可能是cascade-free,甚至可能无法恢复。
5. 恢复系统
5.1 事务失败分类
逻辑错误:由于某些内部错误情况,事务无法完成
系统错误(System errors):数据库系统必须由于错误情况(例如,死锁)而终止活动事务
系统崩溃(System crash):电源故障或其他硬件或软件故障导致系统崩溃。
- 失效停止假设:假定非易失性存储内容未被系统崩溃损坏。数据库系统具有许多完整性检查,以防止磁盘数据损坏
磁盘故障:磁头崩溃或类似的磁盘故障会破坏全部或部分磁盘存储 假定销毁是可检测的:磁盘驱动器使用校验和来检测故障
在不确保事务将提交的情况下修改数据库可能会使数据库处于不一致状态
如果在事务提交后立即发生故障,则不修改数据库可能会导致更新丢失
恢复算法有两个部分:
在正常事务处理期间为确保存在足够的信息以从故障中恢复而采取的操作
在将数据库内容恢复到确保原子性、一致性和持久性的状态失败后采取的操作
5.2 存储结构
- 易失性存储(Volatile storage): 无法在系统崩溃或掉电后存活下来 示例:主内存、高速缓存内存
- 非易失性存储(Nonvolatile storage): 在系统崩溃或掉电后存活下来 示例:磁盘、磁带、闪存、非易失性(电池备份)RAM
- 稳定储存(Stable storage):可在所有故障中存活下来,通过在不同的非易失性介质上维护多个拷贝来近似
5.3 数据访问
每个事物Ti都有一个私有工作区,这个工作区在主存当中
- 物理块(physical block)是驻留在磁盘上的那些块。
- 缓冲块(buffer block)是临时驻留在主内存中的块。
- 磁盘缓冲区(disk buffer)是内存临时存放块的区域
磁盘和主存之间的块移动通过以下两个操作启动:
- input(B) 将物理块 B 从磁盘传输到主存储器。
- output(B) 将缓冲块 B 传输到磁盘,并替换该磁盘的相应物理块。
read(X) 将数据项 X 的值赋给局部变量 xi。
write(X) 将局部变量 xi 的值分配给缓冲区块中的数据项 {X}。
5.4 恢复与原子性
为了确保失败时的原子性,我们首先输出描述对稳定存储的修改的信息,而不修改数据库本身。 有两种方法: 基于日志的恢复(log-based recovery),以及 阴影分页(shadow-paging)
5.5 日志
日志用于维护数据库上的更新活动记录。
典型的日志记录包括:
<Ti start>
,事务 Ti 已启动- 在 Ti 执行 write(X) 之前,写入日志记录
<Ti,X,V1,V2>
,其中 X为数据项标识,V1 是写入前 X 的值(旧值),V2 是要写入 X 的值(新值)。 <Ti committed>
,事务 Ti 已提交。<Ti abort>
,事务 Ti 已中止。
5.6 数据库修改
考虑事务在数据项修改中所采取的步骤:
- 事务在主存中自己私有的部分执行某些计算
- 事务修改主存的磁盘缓冲区中包含该数据项的数据块
- 数据库系统执行output操作,将数据块写到磁盘中
如果一个事务执行了对磁盘缓冲区或磁盘自身的更新,则说这个事务修改了数据库
而事务在主存中修改自己工作区的内容,则不算对数据库的修改。
有两种方式 :
- 立即修改 (Immediate database modification) 允许在事务提交之前对缓冲区或磁盘本身进行未提交事务的更新
- 在写入数据库项之前,必须写入更新日志记录。
- 假设日志记录直接输出到稳定存储,更新的块输出到稳定存储可以在事务提交之前或之后的任何时间进行
- 块的输出顺序可能与它们的写入顺序不同。
- 延迟修改(Deferred database modification)方案仅在事务提交时马上对缓冲区/磁盘执行更新
- 简化了恢复的某些方面
- 但有存储本地副本的开销
事务的提交日志记录输出到稳定存储时,称为已提交事务,如果在事务提交前输出到稳定存储,事务会回滚
事务提交时,事务执行的写入可能仍在缓冲区中,并且以后可能会输出
5.7 undo和redo
定义
undo <Ti、X、V1、V2>将旧值 V1 写入 X
redo <Ti、X、V1、V2>将新值 V2 写入 X
undo(Ti) 将 Ti 更新的所有数据项的值还原为其旧值,从 Ti 的最后一条日志记录向前。
每次将数据项 X 还原到其旧值 V 时,都会写出一条特殊的日志记录 <Ti、X、V> 事务撤消完成后,将写出日志记录。
redo(Ti) 将 Ti 更新的所有数据项的值设置为新值,从 Ti 的第一条日志记录开始,在这种情况下不执行日志修改
执行条件
- undo(延迟修改方案不需要undo):包含记录
<Ti start>
, 但不包含记录<Ti comitted>
或<Ti abort>
。 - redo:包含记录
<Ti start>
并包含记录<Ti comitted>
或<Ti abort>
注意:如果事务 Ti 之前被撤消,并且<Ti abort>
记录写入日志,然后发生故障,则在从故障中恢复时,将redo Ti
5.8 恢复算法(重点)
正常操作
日志记录(在正常操作期间):
<Ti start>
表示事务开始<Ti、Xj、V1、V2>
用于每次更新<Ti commit>
表示事务末尾
事务回滚(正常操作期间) :
- 让 Ti 成为要回滚的事务 ,从末尾向后扫描日志,针对 Ti 的每个日志记录:
- 格式为
<Ti、Xj、V1、V2>
通过将 V1 写入 Xj 来执行撤消, 写入日志记录<Ti、 Xj、 V1>
此类日志记录称为补偿日志记录 - 找到记录
<Ti start>
后,停止扫描并写入日志记录<Ti abort>
- 格式为
故障中恢复(Recovery from failure)
包含两个阶段:
- 先是redo阶段(Redo phase):replay所有事务的更新,无论它们已提交、已中止还是不完整
- 后是undo阶段(Undo phase):undo所有未完成的事务
redo阶段:
- 查找最后
<checkpoint L>
记录,并将undo-list设置为 L(L 是检查点时处于活动状态的所有事务的列表),如果未标注检查点,默认日志开始为检查点。 - 从上方
<checkpoint L>
记录向前扫描- 每当找到
<Ti,Xj,V1,V2>
的记录时,通过将V2写入Xj来redo它 - 每当找到日志记录
<Ti start>
时,请将 Ti 添加到undo-list中 - 每当找到日志记录
<Ti commit>
或<Ti abort>
时,从undo-list中删除 Ti
- 每当找到
undo阶段: (仅对redo阶段之后在undo-list当中的事务操作)
- 从末尾往回扫描日志
- 每当找到日志记录
<Ti、Xj、V1、V2>
,Ti 处于undo-list中时,执行与事务回滚相同的操作:- 通过将 V1 写入 Xj 来执行撤消。
- 写入日志记录
<Ti、 Xj、 V1>
- 每当在 Ti 处于undo-list中的位置找到日志记录
<Ti start>
- 写入日志记录
<Ti abort>
- 从undo-list中删除 Ti
- 写入日志记录
- 当撤消列表为空时停止,即为undo-list中的每个事务都找到了
<Ti start>
- 每当找到日志记录
进行完两个阶段,继续正常操作。
例子:假设<T0 abort>
写到日志之前系统崩溃,描述恢复算法
Redo Phase:
a.Checkpoint的活动事务为T0,T1,因此undo-list为{T0,T1},向较新处扫描
b.找到<T1,C,700,600>
,将600写入C
c.找到<T1 commit>
,从undo-list中删除T1
d.找到<T2 start>
,将T2添加进undo-list
e.找到<T2,A,500,400>
,将400写入A
f.找到<T0,B,2000>
,将2000写入B
到了日志末尾,结束redo phase
Undo phase:
a.经过redo phase之后,undo-list为{T0,T2},向较旧处扫描
b.找到<T0,B,2000>
,T0在undo-list之中,但T0回滚输出的日志是在T0 abort之后有的,跳过
c.找到<T2,A,500,400>
,T2在undo-list之中,将500写入A,输出<T2,A,500>
d.找到<T2 start>
,将T2删除出undo-list,同时输出<T2 abort>
过了检查点,但是由于undo-list当中还有T0,继续往旧处扫描
e.找到<T0,B,2000,2050>
,T0在undo-list之中,将2000写入B,输出<T0,B,2000>
f.找到<T0,start>
,将T0删除出undo-list,输出<T0 abort>
6.事务隔离级别
可串行化调度是保证可一致性的理想方案,但保证绝对的可串行化有可能只能满足极小的并发度。现实中为了提高系统响应时间,SQL标准允许事务可以以一种与其他事务不可串行化的方式来执行,因此有了事务的隔离级别。
以下隔离级别从高到低,具体可以参考MySQL事务隔离级别和MVCC - 掘金 (juejin.cn)
- Serializable — 保证可串行化调度,不允许
读-写
、写-读
的并发操作 - Repeatable read(可重复读) — 只允许读取已提交数据,两个事务读取同一数据项的时候,其他事务不得更新该数据,但不要求该事务与其他事务可串行化
- Read committed(已提交读) — 只允许读取已提交数据,但不要求可重复读
- Read uncommitted(未提交读) — 允许读取未提交数据。这是SQL允许的最低一致性级别
7.缓冲区管理(期末不考先略,后面补充)
【数据库】事务管理概念相关推荐
- 数据库 - 事务管理(ACID)隔离级别 事务传播行为
转载自 数据库 - 事务管理(ACID)隔离级别 事务传播行为 总览: 事务的4大特性(ACID) 原子性(Atomicity) 原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,这和前 ...
- 数据库事务的概念及其实现原理
目录 1. 认识事务 1.1 为什么需要数据库事务 1.2 什么是数据库事务 1.3 事务如何解决问题 1.4 事务的ACID特性以及实现原理概述 2.并发异常与并发控制技术 2.1 常见的并发异常 ...
- spring事务管理-概念部分
这个Spring中的事务呢,是提供了一套可以管理项目中管理事务的机制,使用Spring事务的好处,就是我们的项目里面,不需要手动来管理事务了,那这样的话咱们先复习一下,先复习一下事务,事务复习好像刚有 ...
- 深入Spring数据库事务管理(二)
文章目录 五.数据库的相关知识 (一)ACID特性 (二)丢失更新 第一类丢失更新 第二类丢失更新 (三)隔离级别 脏读 读写提交 不可重复读 幻读 六.选择隔离级别和传播行为 (一)选择隔离级别 ( ...
- spring配置mysql事务管理_Spring 数据库事务管理机制
要点1 Spring事务管理方法编程式事务(TransactionTemplate.PlatformTransactionManager) 声明式事务(配置式.注解式) 2 Spring 注解 @Tr ...
- 数据库事务的概念和ACID特性!你懂了吗,小老弟?!
数据库事务是什么 概念 1.数据库事务是指由一系列语句构成的逻辑单元,或者说是一系列数据库操作的集合.这些语句/操作要么全部提交,要么全部撤回,没有其他的中间状态. 2.事务的状态如图所示,注意它的最 ...
- 数据库事务管理ACID
一.事务 定义:所谓事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位. 准备工作:为了说明事务的ACID原理,我们使用银行账户及资金管理的案例进行分析. [sql] ...
- MySQL数据库事务管理与存储过程
一.事务管理 1.什么叫做事务? 一件事(务)中包含多个操作,在计算机中是指数据库的一组操作,由一条或者多条sql语句组成. 2.事务的作用:避免误操作. 3.事务规则: 要么都执行成功,要么都执行不 ...
- mysql数据库事务的概念_如何理解数据库事务中的一致性的概念?
比较支持@Kai Peng 的答案,只是缺少例子说明. 而其他一些人的答案甚至有明显的错误.最近正好也在研究这方面的东西,不算是回答,就是跟大家讨论讨论. 首先,我们需要搞清楚为什么会出现事务.[1] ...
最新文章
- 互联网各大公司职级和薪资一览
- IOS--工具--使用CocoaPods管理依赖库
- visual basic.net 2019-Visual Basic 16.0新功能
- xcode中用pods管理第三方库转
- 安装vs2008出现的问题
- “大胃王”吃播注意了 国家明确禁止发布量大多吃、暴饮暴食等节目
- 大公司的老板更专注人,小公司的老板更专注事
- abb工业机器人电压不稳_ABB工业机器人应用常见故障九问九答
- G - Ordering Tasks(拓补排序)
- winhex数据恢复linux,winhex数据恢复完整图文教程
- 计算机右键功能总结,电脑小技巧分享:右键菜单功能使用技巧
- 基于java可视化的会议室管理系统
- 分支定界法求解整数规划
- 人生七年,耗时56年跟拍14个孩子,结局道尽人生残酷真相
- PyTorch搭建LSTM实现多变量多步长时间序列预测(二):单步滚动预测
- 牛牛试题排版插件V3更新发布
- 运维简历怎么写项目描述_职场小白怎么写简历?一份好简历=成功一半
- Day 40 多表查询以及pymysql相关操作
- vue多页面多路由开发环境
- HMMER批量比对及结果处理
热门文章
- 浅谈智慧城市管廊综合管理平台的建设
- Unity变换矩阵之如何构建变换矩阵
- flume+kafka+hdfs详解
- 有小孩上学实用 高中课程同步学 v1.0.5 免登陆高级版
- 【嵌入式系统设计与实现】4 十字路口交通灯控制(简易版)
- 开源HTML5拓扑图绘制工具
- 用python让excel飞起来 pdf_这10款良心又好用的PC小工具,让你的电脑更好用!亲测强力推荐!...
- 在天猫618被外国人疯抢的国货,名字都有一个共同规律
- 教你百分百实用监控安装摄像头的方法与技巧
- openjpeg:解决静态链接时未定义引用错误:undefined reference to `__imp_opj_xxxxxxx'