事务原子性&持久性
数据库保证事务的原子性和持久性方式:
Commit Logging
技术,包含Commit Record
和Commit End
,但该技术会存在写日志成功后,才修改数据库数据,会导致IO空闲、长时间占用内存性能问题,因此又有了ARIES理论
下的Write-Ahead_logging
技术write_ahead_logging
技术,ARIES理论,支持提前写入变动数据,但同时带来的是复杂度的提升
在事务提交点上包含两块:事务提交日志、存储数据
- 日志的强制写入与否:
FORCE
: 变动数据必须同时完成提交日志的写入NO FORCE
- 存储数据的提前修改与否:
STEAL
: 变动数据允许提前写入数据库,实现IO提升NO STEAL
- Commit Logging允许
NO-FORCE
,但不允许STEAL
- Write-Ahead Logging 允许
NO FOCRCE
,不强制提交日志的提前写入,同时支持STEAL
允许提前写入数据,带来的问题就是复杂度的提升,日志回滚变得更加复杂了
Write-Ahead Logging 日志回滚
Undo Log
Write-Ahead Logging
允许 NO-FORCE
,也允许 STEAL
,它给出的解决办法是增加了另一种被称为 Undo Log
的日志类型,当变动数据写入磁盘前,必须先记录Undo Log
,注明修改了哪个位置的数据、从什么值改成什么值,等等,以便在事务回滚或者崩溃恢复时根据Undo Log
对提前写入的数据变动进行擦除。
此前记录的用于崩溃恢复时重演数据变动的日志就相应被命名为Redo Log
,一般翻译为“重做日志”
崩溃恢复时执行的三个阶段
针对STEAL
,增加了Undo Log
和Redo Log
,重做阶段和回滚阶段的操作都应该设计为幂等
分析阶段(Analysis)
:该阶段从最后一次检查点(Checkpoint
,可理解为在这个点之前所有应该持久化的变动都已安全落盘)开始扫描日志,找出所有没有 End Record 的事务,组成待恢复的事务集合,这个集合至少会包括Transaction Table
和Dirty Page Table
两个组成部分。重做阶段(Redo Log)
: 该阶段依据分析阶段中产生的待恢复的事务集合来重演历史(Repeat History),具体操作为:找出所有包含 Commit Record 的日志,将这些日志修改的数据写入磁盘,写入完成后在日志中增加一条 End Record,然后移除出待恢复事务集合。回滚阶段(Undo Log)
: 该阶段处理经过分析、重做阶段后剩余的恢复事务集合,此时剩下的都是需要回滚的事务,它们被称为 Loser,根据 Undo Log 中的信息,将已经提前写入磁盘的信息重新改写回去,以达到回滚这些 Loser 事务的目的。