文章目录
- 数据库系统原理与实践 笔记 #11
- 事务管理和并发控制与恢复
- 事务概念
- 转账的例子
- 事务ACID特性
- ACID特性
- 事务原子性和持久性
- 事务隔离性
- 调度
- SQL中的事务定义
- 可串行化
- 事务的简化视图
- 冲突的指令
- 冲突可串行化
- 可恢复性
- 级联回滚
- 无级联调度
数据库系统原理与实践 笔记 #11
事务管理和并发控制与恢复
事务概念
- 事务是构成单一逻辑工作单元的操作集合
- 事务是访问并可能个您各种数据项的一个程序执行单元
- 事务由事务开始(begin trasaction)与实务结束(end transaction)之间执行的全体操作组成
- 事务管理处理的两个主要问题:
- 各类故障恢复,如硬件故障,系统崩溃等
- 多个事务的并发执行
转账的例子
- 从账户A过户$50到账户B的事务:
- 1.read(A)
- 2.A := A - 50
- 3.write(A)
- 4.read(B)
- 5.B := B + 50
- 6.write(B)
- 原子性要求:在3之后、6之前,如果事务出现故障,钱就会丢失,从而导致数据库的不一致性,系统应该保证部分执行的事务的更新不会体现在数据库中
- 持久性要求:一个事务成功完成后,它对数据库的改变必须是永久的,即使出现系统故障
- 一致性要求:事务执行结束后A和B的总和不变
- 隔离性要求:如果3到6之间,另一个事务T2允许进入部分更新的数据库,该事务将会看到一个不一致的数据库(A+B的和可能会少于其实际值)
- 可以通过将事务串行化来保证隔离性,但是并发执行事务有很大的性能优势
事务ACID特性
ACID特性
- 事务是访问并可能更新各种数据项的一个程序执行单元
- 原子性(Atomicity):事务的所有操作在数据库中要么全部反映出来,要么完全不反映
- 一致性(Consistency):事务隔离执行时(即在没有其他事务并发执行的情况下)保持数据库的一致性
- 隔离性(Isolation):尽管多个事务可能并发执行,但是每个事务都感觉不到系统中有其他事务在并发地执行
- 持久性(Durability):一个事务成功完成后,它对数据库的改变是永久的,即便系统出现故障时也是如此
事务原子性和持久性
- 事务的状态包括:
- 活动的:初始状态,事务执行时处于这个状态
- 部分提交的:最后一条语句执行前
- 失败的:发现正常的执行不能继续后
- 中止的:事务回滚并且数据库已恢复到事务开始执行前的状态后(中止之后可以重新开始事务,也可以杀死事务)
- 已提交的:成功完成执行的事务(撤销已提交事务所造成影响的唯一方法是执行一个补偿事务)
事务隔离性
- 事务处理系统通常允许多个事务并发地执行,优点是:
- 提高吞吐量和资源利用率
- 减少等待时间
- 并发控制机制:实现事务隔离性的机制(控制并发的事务之间的相互作用,来避免他们破坏数据库的一致性)
调度
- 调度:执行执行顺序,指定并发执行事务的指令执行的时间顺序
- 一组事务的一个调度必须包含这一组事务的全部执行
- 必须保持指令在各个事务中出现的顺序
- 一个事务成功执行后,会有一条指令作为最后的声明:事务默认提交指令commit为其最后一条执行
- 一个事务没有成功完成时,会用一条中止指令abort来作为最后的声明
SQL中的事务定义
- 数据操纵语言(DML)必须包含用于说明构成事务的活动集合的结构
- SQL标准规定事务的开始是隐式的
- 事务的结束用下列SQL语句之一来表示(work可选):
- Commit [work]:提交当前事务并开始一个新的事务
- Rollback [work]:回滚当前事务
- 在几乎所有的数据库系统中,缺省每个SQL语句如果成功执行的话,也立即隐式提交事务(这种隐式提交也可以通过数据库指令关闭)
可串行化
- 基本假设:每个事务都可能保持数据库的一致性
- 事务的串行执行是可以保持一致性的
- 如果一个调度等级碍于一个串行调度,那么这个调度就是可串行化的
- 按调度的不同形式可分为:冲突可串行化、视图可串行化
事务的简化视图
- 只考虑read和write指令
- 假设事务在read和write指令之间可以对本地缓冲区的数据进行任意的操作
- 简化的调度只包含read和write指令
冲突的指令
- 两条连续指令 l i l_i li与 l j l_j lj分别属于事务 T i T_i Ti和 T j T_j Tj,当且仅当数据项Q被 l i l_i li和 l j l_j lj同时访问,并且至少有一个指令执行了write Q操作才会发生冲突
- 1. l i = r e a d ( Q ) l_i = read(Q) li=read(Q), l j = r e a d ( Q ) l_j=read(Q) lj=read(Q),不冲突
- 2. l i = r e a d ( Q ) l_i = read(Q) li=read(Q), l j = w r i t e ( Q ) l_j=write(Q) lj=write(Q),冲突
- 3. l i = w r i t e ( Q ) l_i = write(Q) li=write(Q), l j = r e a d ( Q ) l_j=read(Q) lj=read(Q),冲突
- 4. l i = w r i t e ( Q ) l_i = write(Q) li=write(Q), l j = w r i t e ( Q ) l_j=write(Q) lj=write(Q),冲突
冲突可串行化
- l i l_i li和 l j l_j lj之间的冲突迫使它们之间有一个逻辑时间顺序
- 一个调度中,如果 l i l_i li和 l j l_j lj在时间上连续并且不发生冲突,则可以交换这两条指令的顺序
- 如果调用S可以通过一系列非冲突指令交换转换成S’,我们称S和S’是冲突等价的
- 若一个调度S与一个可串行调度冲突等价,则称调度S是冲突可串行化的
可恢复性
需要了解并发运行的事务的失败会产生什么影响
-
可恢复调度:如果 T j T_j Tj读取了之前由 T i T_i Ti所写的数据项,则 T i T_i Ti需先于 T j T_j Tj提交
-
下面的调度无法恢复,如果 T 9 T_9 T9在read之后直接提交
-
如果 T 8 T_8 T8要中止, T 9 T_9 T9会读到一个不一致的数据A。因此,数据库必须保证调度可恢复
级联回滚
-
级联回滚:因单个事务故障导致一系列事务回滚
-
如果没有一个事务是提交的,如果 T 10 T_{10} T10失败, T 11 T_{11} T11和 T 12 T_{12} T12必须回滚,会导致撤销大量工作
无级联调度
- 无级联调度:对于每对事务 T i T_i Ti和 T j T_j Tj,如果 T j T_j Tj读取了先前由 T i T_i Ti所写的数据项,则 T i T_i Ti必须在 T j T_j Tj这一读取操作前提交(不会发生级联回滚)
- 无级联调度是可恢复的