MIT6.830
介绍
课程官网:6.5830/6.5831: Lecture Notes and Assignments (mit.edu)
项目仓库:MIT-DB-Class/simple-db-hw-2021 (github.com)
理论
Lecture5
Buffer Pool Optimizations
Lecture7
Basic Join Summary
上面的图列举了将两个表进行join
操作时,CPU和I/O的开销。{R}
指表R中行数,|R|
指表R在磁盘上存储的页面数,如果每页存B条记录,则|R|={R}/B
。
External Join Summary
Lecture8
Query Optimization Objective
谓词下推(Predicate Pushdown):将尽可能多的判断更贴近数据源,以使查询时能跳过无关的数据。用在SQL优化上来说,就是先过滤再做聚合**等操作。
Lecture10
Transaction:
- Begin:在开始修改数据库的SQL语句之后
- Commit:使事务生效,即持久化到磁盘中,对其他事务可见。即使数据库崩溃了也同样有效。
- Abort:撤销事务的所有操作。
View Serializability(视图可串行化)
一个在调度S中特定的指令顺序被认为是等价于串行顺序S’当仅当:
- 在 S 中读取的每个值都与在 S’ 中读取的相同。
- 每个对象的最终写入都由 S 和 S’ 中的同一个事务 T 完成。
以较为简略的表达方式,所有在S中的事务“观察”到的数值与在S’中的相同,并且事务运行后的最终状态是相同的。
左边的调度次序S,和右边的串行化先T1后T2的等价。
- 先T1后T2,那么最后写入的B是由T2执行的,不符合”每个对象的最终写入都由 S 和 S’ 中的同一个事务 T 完成。“
- 先T2后T1,那么T1读取到的A是被T2更新之后的,不符合”在 S 中读取的每个值都与在 S’ 中读取的相同。“
Conflict Serializability(冲突可串行化)
如果可以通过交换不冲突的操作得出串行调度,那么该调度就是可冲突串行化的。
换言之:
对于所有冲突操作对,(o1 in T1,o2 in T2)
要么o1恒先于o2,要么o2恒先于o1。
判断方法:优先图无环
是冲突可串行化的一定是视图可串行化的,反之不一定。
实现冲突可串行化
两段锁
- 共享锁S 排他锁X
- 实现了冲突可串行化
- 访问对象需要获得共享锁,写入对象需要获得排他锁(或将共享锁升级为排他锁)
- 一个事务不可以释放任何锁,直到它获取了所有锁。
- 只有在最后一个锁被获取且对该对象的操作完成后,才释放锁。先获取后释放。(也就是只能在扩张阶段获取锁,不可释放锁;在收缩阶段只能释放锁,不可以获取锁)如下图
二段锁问题:
Deadlocks
相互等待获取锁,而导致谁都无法释放锁。
Cascading Aborts(级联终止)
Strict Two-Phase Locking (Strict 2PL):
- 可以避免级联终止通过持有排他锁直到事务结束
- 保证事务永远不会读取其他事务为提交的数据
- 可以解决”脏读“问题
不同: - 在对于某个对象操作结束和已经获取最新的锁后,仅释放共享锁
- 只有当事务提交后,才释放排他锁
Rigorous Two-Phase Locking Protocol:
- 仅当事务提交后,才释放所有的锁。
- 提交顺序与串行顺序一致
隔离等级
再探幻读!什么是幻读?为什么会产生幻读,MySQL中是怎么解决幻读的?-CSDN博客
OCC(Optimistic concurrency control)
假定事务在访问数据时,不发生冲突。只在验证阶段,检测冲突,冲突则abort。
三个阶段:Read Validation Wrte
Forward Validation(前馈验证)。如果事务Ti的验证时刻<事务Tj的验证时刻
- 事务Ti在事务Tj开始前就已经完成。意味着无相互影响
- 事务Ti在事务Tj开始Write阶段前完成,并且
WriteSet(Ti) ∩ ReadSet(Tj) = Ø
。也就是Ti没有写入任何被Tj读取的对象。 - 事务Ti完成了Read阶段在事务Tj完成其Read阶段之前,并且
WriteSet(Ti) ∩ ReadSet(Tj) = Ø
和WriteSet(Ti) ∩ WriteSet(Tj) = Ø
。也就是事务Ti没有写入任何被Tj读取或写入的对象。
意向锁
IS:意向共享锁:表明事务在其子节点(表/页/记录)设置共享锁
IX:意向排他锁:表明事务在其子节点(表/页/记录)设置互斥锁
获取和释放锁的顺序:
- 自上而下获取锁,先获取祖先节点的意向锁,再获取共享/排他锁
- 自下而上释放锁。
MVCC(Multi-Version Concurrency Control)
【MySQL笔记】正确的理解MySQL的MVCC及实现原理_mysqlmvcc实现原理-CSDN博客
Snapshot Isolation
- 当事务启动时,它会记录一个时间戳T。
- 所有读取均从DB版本为T执行。
- 所有的写都在各自的缓冲区进行
- 当事务提交时,DBMS检查冲突
废弃时间戳为T1的TA1,如果存在TA2- TA2在T1之后,但在TA1之前提交
- TA1和TA2更新了相同的对象
因为T2在操作W(X:=v3)之前,T3已经提交了对X的修改,并且该修改位于T2开始之后,T2提交之前。
快照隔离不能防止写-读冲突,因为它不检查是否读取从另一个事务写入的内容
Lecture13
数据库故障类型
- 事务故障:由于某些内部错误(如违反完整性约束条件)导致事务无法完成;内部状态错误(死锁)
- 系统故障:软件故障(OS或DBMS,除零错误等);主机异常奔溃
- 存储介质故障:磁盘损坏。这个类型是无法恢复的,没有DBMS可以从该类异常中恢复。
易失性内存主要充当缓冲区,用户与数据库的交互全都是在内存中完成,然后写回磁盘的
- 首先将目标记录复制到内存中
- 在内存中执行写入操作
- 将脏数据写回磁盘
数据库崩溃后
- 内存会被重置
- 磁盘是持久化的
在崩溃后,Recovery机制需要保证:
- 原子性:部分完成的事务需要回滚
- 持久性:已提交的事务需要在稳定的存储中,如磁盘
使数据库进入事务一致状态,已提交的事务得到完全反映,未提交的事务被完全撤销。
UNDO:消除不完整或终止的事务对数据库的影响。某些事务可能已将其未提交状态写入表中–需要撤销
REDO:重新执行已提交的事务对数据库的影响。某些事务在提交之前可能还没有刷新所有的状态到他们的表中–需要重做
Steal Policy:DBMS是否允许未提交的事务覆盖磁盘上最新已提交的数据。
STEAL:允许,意味着磁盘上可能有uncommitted的数据,需要通过undo日志支持回滚。(原子性)
NO-STEAL:不允许
Force Policy:DBMS是否要求事务提交时,必须将所有更新刷盘。
FORCE:需要
NO-FORCE:不需要。这种情况磁盘上可能还是前镜像状态,需要redo日志来恢复后镜像状态。(持久性)
当代数据库存储引擎大部分都有 undo log 和 redo log,那么它们就是 steal/no-force
策略的数据库。
提前写入日志(WAL)原则:在执行实际操作时,先写日志后操作。避免操作失败后,无法通过日志恢复。
Checkpoint
数据库的日志会无限增长,导致crash后,重新执行日志来恢复数据的时间越来越长。checkpoint的机制就是用来解决这个问题的。它类似于快照,创建一个checkpoint之后,之前已提交的事务的日志则不必重新执行。
- 暂停所有查询
- 写日志记录到磁盘中
- 写缓冲池中的脏页到磁盘中
- 添加Checkpoint的日志条目到磁盘中
- 重新开始查询
ARIES
- Write-Ahead Logging:写前日志+(STEAL+NO-FORCE policies)
- 使用Redo重复历史
- 记录Undo过程中的更改
Fuzzy Checkpoint
图解数据库Aries事务Recovery算法 - 黑客画家的个人空间 - OSCHINA - 中文开源技术交流社区