保证原子性的两种做法:日志和影子分页
事务做到一半崩溃了,改了一半的数据怎么还原?
- 日志:改之前先记下旧值(undo),回滚或崩溃后据此撤销。
- 影子分页:要改的页先复制一份(写时复制),在副本上改;提交时把页表的根指针切过去。崩溃了就丢掉没切过去的副本。
影子分页听起来更干净,但几乎没人用在通用数据库里:
- 改过的页散落在磁盘各处,变成大量随机写
- 提交时要刷所有改过的页和页表
- 旧页要回收,也很难支持多个事务并发写
日志是顺序追加,提交时只要把日志刷盘。
容易混的一点:崩溃后撤销没提交的修改靠 undo,属于原子性;重做已提交的修改靠 redo,属于持久性。