DBMS/数据库(九)故障、撤销、恢复和备份

335 阅读9分钟

故障、恢复和备份

故障、恢复和备份简述

什么是故障

DBMS系统在运行过程中由于各种因此可能会发生一些故障。如软件代码逻辑层次、操作系统故障、计算机故障等。

什么是恢复

当DBMS发生故障后,数据可能会丢失,后续DBMS能够恢复丢失的数据。

什么是备份

预先的备份DBMS所管理的数据,避免故障导致数据丢失。

故障

事务故障

DBMS 在事务执行过程中出现故障。

  • SQL 使用不正确导致的故障;如外键关联等。
  • DBMS 内部错误;如死锁、并发问题等。
系统故障

系统级别的故障。

  • DBMS 进程崩溃;如内存占用过高等、BUG等。
  • 操作系统层面出现问题。
  • 计算机崩溃;如蓝屏、死机等。
存储介质故障

数据所在的介质故障。

  • 磁盘损坏;

注意:磁盘损坏导致的故障无法轻易恢复。因此只能采用复制或备份技术尽可能的实现。

恢复

为了解决故障,因此出现了恢复技术,避免故障导致的数据问题。

回滚

回滚解决了事务执行过程中出错的问题。

撤销

等同于回滚,只是表达角度不同,回滚着重于故障后的逻辑,而撤销着重于数据的恢复。

恢复

恢复解决系统故障,即系统故障发生后,DBMS重启时的记录重建

简单写入

为了解决事务提交后,系统故障导致的数据丢失问题,DBMS可以在事务提交时 强制持久化记录数据 到磁盘。从而实现恢复。

优点:系统故障的恢复很简单,重启DBMS后什么也不用做。

缺点:性能非常差,数据很大时,磁盘IO过于耗费时间。

WAL(预写数据)

为了解决系统故障和优化强制持久化的性能问题,记录数据的写入不在事务提交时持久化,而是写入到Buffer中,由DBMS异步线程或操作系统控制。此时事务提交后,如果出现系统故障,可能会使得Buffer未完全持久化到磁盘导致数据丢失。没有解决恢复问题

而为了实现恢复,WAL 采用 log 技术,由一个log去记录事务中的每个更新操作。当出现系统故障后,再次重启DBMS时,DBMS会 根据 log 中的事件 记录 重建 记录数据。从而实现恢复。

优点:提升了DBMS性能。

缺点:额外的log记录、系统故障后必须依赖log完成数据的恢复

注意:log的写入必须是在记录数据持久化之前完成(通常log会使用Buffer优化) ,否则log都不完整,肯定没办法恢复。

物理日志

存储到磁盘中的日志是物理日志文件,WAL中的日志就属于此类。

逻辑日志

仅仅是逻辑层次的日志,实际实现过程中不一定是通过日志文件的方式实现。

Undo Log

为了解决事务故障,产生了undo log,undo log中记录了修改前的旧数据。undo log只是一个逻辑日志,本质实现是一个结构,存储在表中间中(数据页)。

在一些DBMS中,Undo log也用于实现MVCC技术中的版本概念。

Undo Log 实现原理

必须持久化?会丢失吗?

更新记录时:

  1. 更新前创建一个undo log存储到表中间中;
  2. 更新数据并存储回滚指针;

回滚时:

  1. 找到当前引用的回滚记录;
  2. 执行回滚;
为什么不需要 undo log buffer

Undo log只是一个逻辑日志,因此使用表空间的Buffer即可,不需要额外的Buffer。

undo log 防止丢失

undo log由于使用的是表空间,那么就是面临系统故障后的数据丢失问题,而在系统故障后事务需要回滚时,就会出现错误。

通常创建undo log时,redo log也会参与,即通过redo log保证了undo log的安全性。DBMS恢复时,也会通过 redo log 重建undo log(实际上就是表空间的数据页)。

Undo Log 什么时间被删除

事务提交后,由Purge线程删除。

Redo Log

为了解决系统故障,出现了Redo log,Redo Log记录了修改后的记录。实际上就是WAL的具体实现。记录了每一个记录数据的变更。从而在系统故障后进行数据重建。Redo log是一个物理日志,一般用单独的物理文件存储。

系统故障发生时:

  • 如果 事务提交成功 ,那么 Redo Log必然持久化成功 ,即 记录肯定可以恢复;事务提交会强制持久化redo log,此时无论记录数据是否从buffer poll中持久化完成,都不影响后续的恢复重建。
  • 如果 事务未提交那么Redo Log 有可能持久化成功 ,也 可能丢失 ,而Buffer Poll可能持久化成功,也可能丢失,不过redo重放的数据和真实磁盘中的记录数据不一致也不重要,因为反正事务未提交,那么就执行undo回滚即可。
Redo Log 实现原理

更新记录时:

  1. 先更新Buffer Poll中的记录。
  2. 再添加一条redo事件日志到redo log buffer。
  3. 异步线程会刷新Buffer Poll和redo log buffer。

重建时:

  1. 根据redo日志重放。
  2. 如果redo重放完成后,发现一些事务未提交,那么执行undo回滚。
恢复(重建)过程

redo日志强制持久化完成后才可以返回给用户commit成功。

  • 场景1:事务提交,redo log = 磁盘中的记录数据;(redo中只要事务commit,那么必然重建完整记录
    • 原因:redo持久化成功,buffer poll持久化成功后,此时系统故障。
    • 重建:重放redo内容,由于幂等和事务已提交,因此记录数据被恢复。
  • 场景2:事务提交,redo log > 磁盘中的记录数据;(redo中只要事务commit,那么必然重建完整记录
    • 原因:redo持久化成功时,系统故障。此时buffer poll剩余数据数据还未持久化,但有部分数据已经持久化了。
    • 重建:重放redo内容,由于当前事务已经commit,因此记录数据被恢复。
  • 场景3:事务未提交,redo log = 磁盘中的记录数据;(redo中只要事务没有commit,那么无论redo和记录数据是否一致,后续都会undo
    • 原因:系统故障后,redo log 和 磁盘记录数据持久化进程一致。
    • 重建:重放redo log,回滚,因为redo中记录的事务是未提交的。
  • 场景4:事务未提交,redo log > 磁盘中的记录数据;(redo中只要事务没有commit,那么无论redo和记录数据是否一致,后续都会undo
    • 原因:系统故障后,redo log 持久化的事件多而Buffer Poll持久化的数据少。
    • 重建:重放redo log,回滚,因为redo中记录的事务是未提交的。
  • 场景5:事务未提交,redo log < 磁盘中的记录数据;(redo中只要事务没有commit,那么无论redo和记录数据是否一致,后续都会undo
    • 原因:系统故障后,redo log 持久化的事件少,而Buffer Poll持久化的数据多。很难出现,因为redo log通常尽可能的早于Buffer Poll的持久化。如MySQL中Log Buffer没1s刷新,而Buffer Poll每30s刷新。
    • 重建:重放redo log,回滚,因为redo中记录的事务是未提交的。
事务提交前记录数据是否会落库

会,WAL的实现就是 预写日志+force redo。因此在未提交时,记录数据可能部分已经在磁盘中了。如果此时系统故障,那么重建时,由于redo日志记录的操作不完整,所以还会使用undo日志回滚当前操作。

注意:redo日志并不是在记录更新后才写事件,而是在更新前后都记录一次事件。

为什么使用 redo log buffer

WAL是一个很方便的技术,但由于预先写数据情况下必须保证log的准确性,因此log一定需要先于记录数据的存储。

而在此情况下,每次log事件的物理存储都需要一次磁盘IO,所以为了优化性能,使用了buffer进行缓冲。而异步再去持久化buffer。

Log Buffer 优化了Log的存储性能,但由于异步持久化,因此事务未提交时的系统故障会使得Log内容和磁盘记录数据不一致,因此必须考虑使用undo回滚(即使一致也需要回滚,因为在用户看来,事务并没有成功) 。而事务 提交时 ,DBMS会 强制刷新log buffer,因此保证了数据的恢复。

redo log buffer 丢失数据

严格的redo由于性能,因此使用了buffer,而buffer由于在事务未提交时是异步刷新,因此在事务未提交时系统故障后,log buffer可能丢失数据,造成的结果就是log buffer和buffer poll持久化的数据不一致。

不过这种情况是可以忽略的,只需要在恢复时使用undo回滚未提交的事务数据即可,但需要保证undo不能丢失。

为什么先写 redo log buffer

基于WAL思想,预写记录数据 + Force Log。因此Log的记录就必须准确,即在持久化记录数据之前完成redo log记录。

为什么批量持久化 redo log buffer

同 ‘为什么使用 redo log buffer’ 问题一样,为了优化 额外的log 存储性能,批处理是一个很好的技术。

redo log buffer 的 flush 策略
  • 每间隔一定时间;
  • Log Buffer 空间不足时;
  • 事务提交时;不需要每次事件都持久化,即保证了WAL的条件,又提升了性能。
  • DBMS进程正常退出时;
  • checkpoint时;
CheckPoint

简单理解为检查点时,DBMS需要清场。避免redo log物理文件膨胀;通常redo log都是一组用于实现高可用,太多事件则覆盖最早数据,类似于环。

备份

本地磁盘备份

使用外设硬件实现本地备份。

远程备份

一些服务器专门用于实现远程磁盘的备份。

复制

将DBMS实现为分布式系统,同时多个DBMS提供服务,通过内部通信和数据的同步、异步复制实现备份。