数据库停电了怎么办,内存是不会存储数据的
就算数据库停电,也要保证数据库的ACID
所以在没有停电的时候就要多做一些事情来防患于未然
任务:
- failure classification 故障级别
- buffer pool policies 缓冲池策略
- shadow paging 影子页
- write-ahead log WAL预写日志
- logging schemes 日志的架构
- checkpoints 检查点
failure classification
- txn failures 事务级
- system failures 系统级
- storage media failures 存储介质的故障
txn failures
- logical errors 逻辑错误,回滚
- internal state errors 内部状态错误,死锁
这个级别的错误是必须要考虑的
system failures
- software failures 数据库的bug
- hardware failure 硬件故障 断电
也是要考虑的
storage media failures
- non-repairable hardware failure 无法修复的故障
不用管,但是运维要管
我们要跟用户保证,只要commit,数据就不能丢
如果abort了,那这个事务就是没有发生一样
undo 撤销操作
redo 重做操作
首先,数据库要选择在commit时,数据库用不用讲数据从内存刷入磁盘中,而且刷的时候是刷整个tuple还是只刷新更新的数据
steal policy 是否会产生脏页
steal,可以刷脏页的
no-steal,不可以刷脏的
no-steal+force 非窃取+强制
先copy干净页,只修改自己的,然后刷进磁盘
优点好实现,没有redo和undo操作,缺点就是性能上的,数据过多会导致内存溢出(不能支持写的量大于内存量)
shadow page 影子页
要修改页拷贝一份,更新在拷贝页中,读写在新的拷贝页中做,边改边刷新进入磁盘,在commit时,修改指针,再垃圾回收操作
undo实现就是删掉影子页,对影子页和磁盘中的拷贝页都当垃圾回收掉
redo是不需要实现的,只要commit之后,数据就固化了
优点是:中间操作可以刷入磁盘
问题是:刷的更频繁了,冗余操作太多了,commit时操作太多了,容易造成数据碎片化
WAL write-ahead log 预写日志,窃取非强制的
在磁盘中单开一个data file(日志文件),保持txn对数据的修改,我们假设日志文件是存在理想文件夹中的,日志本身有足够的信息支持undo和redo操作
数据库在将操作内容写入磁盘之前将修改内容写入日志中,当用户commit时
事务开始时写一个begin,提交的时候写一个commit,写commit日志的时候保证要讲所有的日志都刷入盘中
WAL 格式
- txn id
- object id 修改的数据是什么东西
- before value 修改之前是什么
- after value 修改之后是什么
UNDO 用before value实现
REDO 用after value实现,从磁盘上的日志写入磁盘中的数据存储位置
WAL例子,先写日志,再写数据,日志落入磁盘中,用户就可以退出来,真正的数据在内存中,但是数据库中数据还没有更新,具体什么时候更新是数据库的事情
用户commit之前必须全部刷入磁盘中
优化:group commit,要减少用户提交次数,因为磁盘存取是很慢的
让多个用户的数据搞到一起提交,大家都等一等,但是不能让等太长时间,就算页没满就刷入磁盘,也不要让用户等太久
内存中的数据什么时候刷盘?
要运行性能而不要恢复性能
logging schemes 本身格式
physical logging 物理日志,记录每一个页到二进制级别的变化
logical logging 逻辑日志,记录操作本身,sql语句
物理日志的改进:physiological logging,记录物理页的变化,记录页的槽的变化,
checkpoints 存档点
什么时候存档,什么时候删档
到了存档点,之后
- 没有落盘的log先落盘
- 脏页落盘
- 日志中写一个checkpoint
宕机之后,因为T2提交了,要对T2redo,T3执行了一部分但没有commit,要对T3undo