事务
- 事务:由某个用户执行的一个不能够被打断的对数据库的操作序列
- 影响因素
- concurrency 并发控制
- abort
- crash 故障恢复
- 事务的四个性质:ACID
- Atomicity:要么全部发生,要么都不发生
- Consistency:满足数据约束
- Isolation:并发事务的可串行化
- Durability:数据不丢失
事务控制
-
事务控制语句
-
begin transaction
数据定义命令(DDL):每条数据定义命令为一个单独的事务
自动提交方式(
set autocommit on|off
):每条访问命令为单独的事务数据操纵命令(DML)
-
commit transaction
-
rollback transaction
savepoint
-
-
事务控制命令(DCL)
set autocommit on|off
set transaction readonly|readwrite
set transaction isolation level readuncomitted|readcomitted|readrepeatable|serializable
-
并发错误
- 更新丢失:对多个事务并发修改同一个数据对象的情况未加控制
- 脏读:一个事务读取到了另外一个事务没有提交的数据
- 不可重复读:在两次连续的读操作间插入了另一个事务的写操作
- 幻象读:在两次连续的查询操作间插入了另一个事务的插入操作
隔离级别 | Dirty Read | Non-repeatable Read | Phantom Read |
---|---|---|---|
Read uncommited | Possible | Possible | Possible |
Read commited | Possible | Possible | |
Repeatable read | Possible | ||
Serializable |
事务的语句组成
- 事务控制操纵
- 事务开始:START T0
- 提交事务:COMMIT T0
- 回退事务:ABORT T0
- 数据访问操纵
- INPUT(A)
- OUTPUT(A)
- READ(A,t)
- WRITE(A,t)
并发控制
实现并发事务的可串行化调度
调度定义
- 串行执行:多个事务依次执行
- 并发执行:交替执行来自不同事务的操作
- 调度(Schedule, History):DBMS 中实际执行序列
- 可串行化调度:对数据库状态的影响和某个串行调度相同
- 事务与调度表示方法
- 事务: $T_i$
- 事务 $T_i$ 读写数据库对象 $X$:$r_i(X)$
- 冲突:一对相邻操作,交换顺序改变结果
- 同一事务相同操作是冲突
- 不同事务对同一数据对象的读-写冲突
- 不同事务对同一对象的写冲突
- 冲突可串行化调度:通过非冲突操作交换可变为串行调度
- 充分条件
- 冲突等价
- 优先图无环
- 视图等价:对每个数据项
- 一方能读到初始值,另一方也能读到初始值
- 如果在调度S中事务Tk执行了rk(D),并且读到的是由事务Tj写入的D的值,则在调度H中事务Tk的rk(D)读到的也必须是由事务Tj所写入的D的值
- 如果在调度S中是由事务Tk来执行最后一条关于D的写操作wk(D),则在调度H中也一定是事务Tk执行最后一条关于D的写操作wk(D)
- 视图等价是冲突等价的必要非充分条件
锁
- 锁
- 排它锁(X-lock)
- 共享锁(S-lock)
- 锁协议
- 一级锁协议:写前必须申请X锁并维持到事务执行结束(丢失修改)
- 二级锁协议:一级+读之前申请S锁并维持到读操作完成后(丢失修改,脏读)
- 三级锁协议:一级+读之前申请S锁并维持到事务执行结束(丢失修改,脏读,不可重复读)
- 两阶段锁协议(2PL)
- 申请并获得锁
- 释放所有申请的锁
- 两阶段锁事务:所有锁请求先于解锁请求
- 由2PL事务所构成的任意合法调度S都是冲突可串行化的
- 锁粒度:一把锁可以封锁的数据对象大小
- 锁粒度大,系统并发度低,并发控制开销小
- 多粒度封锁:同时支持多种封锁粒度
- 多粒度树
- 意向锁
- 意向共享锁(IS锁)
- 意向排它锁(IX锁)
- 共享意向排它锁(SIX锁)
- 意向锁加锁算法
- 如果对一个结点加‘意向锁’,则说明该结点的下层结点正在被加锁
- 对任一结点加锁时,必须先对它的上层结点加‘意向锁’
- 申请封锁:自上而下
- 释放封锁:自下而上
- 锁相容矩阵
- 死锁:循环等待现象
- 预防法
- 顺序申请法
- 一次申请法
- 解除法
- 超时死锁算法
- 事务执行超时
- 锁申请超时
- 等待图法
- 时间戳死锁检测法
- 等待-死亡方案
- 伤害-等待方案
- 牺牲年轻事务
- 超时死锁算法
- 预防法
- 活锁:部分事务因封锁申请无法满足长期等待
- 先来先服务
数据库恢复
数据库遭到破坏后及时恢复的功能
- 故障分类
- 小型故障
- 事务内故障
- 中型故障
- 系统故障
- 外部影响
- 大型故障
- 磁盘故障
- 计算机病毒
- 黑客入侵
- 小型故障
- 数据转储(dump):定期将数据库内容复制到其它储存设备
- 静态转储/动态转储
- 海量转储/增量转储
- 结合数据库日志:转储的开始与结束点,事务更新操作
- 数据库镜像
- 日志:自动记载修改型操作的数据更新情况文件
- undo日志:用于被放弃事务的撤销工作
- 记录格式
- 开始:Start T
- 提交:Commit T(须在事务所有操作写入磁盘后写入)
- 放弃:Abort T
- 更新:T,X,V (V是原来的值,须在新值写入磁盘前写入)
- Flush Log: 内存中的日志记录写到磁盘
- 恢复过程:从尾部开始扫描整个日志,对未提交事务恢复数值,加入 Abort T
- 记录格式
- 检查点
- 处理过程
- 系统停止接受 Start T
- 等待当前活跃事务被提交或中止
- 写入所有日志
- 写入 CKPT
- 非静止检查点
- 处理过程
- redo日志:用于已提交事务的重做工作
- V是更新的值
- Commit 写入后修改
- 冗余修改
- undo/redo日志
- T,X,v,w
- 事务提交和写数据库磁盘的顺序是随机的
- 故障恢复
- undo 未提交事务
- redo 已提交事务
- undo日志:用于被放弃事务的撤销工作