数据库概论 (七)恢复技术

数据库恢复技术

保证数据库数据的可靠性。

一个简单的例子:

  • 从A账户向B账户转账1000元人民币
  • 读取A账户的余额
  • 余额足够,扣除一千元
  • 读取B账户的余额
  • 将余额加上1000元

在扣除余额到余额增加的步骤之间,如果出现了系统性的故障,硬件故障,导致整个流程没有顺利完成,就会导致错账。

简单分析可知出错是因为整个流程并不是原子性的,或者说,想要完成原子性,但是没有对中间错误发生的预案。

事务

事务的基本特性有四个特性,ACID,保证了事务的原子性,一致性,永久性,隔离性。

1. 原子性(Atomicity)

事务被视为不可分割的最小单元,事务的所有操作要么全部提交成功,要么全部失败回滚。

回滚可以用回滚日志(Undo Log)来实现,回滚日志记录着事务所执行的修改操作,在回滚时反向执行这些修改操作即可。

2. 一致性(Consistency)

数据库在事务执行前后都保持一致性状态。在一致性状态下,所有事务对同一个数据的读取结果都是相同的。如果出问题可能会导致不可重复读,幻影读等问题。

3. 隔离性(Isolation)

一个事务所做的修改在最终提交以前,对其它事务是不可见的。在并发的时候使用锁机制来保证隔离性。

4. 持久性(Durability)

一旦事务提交,则其所做的修改将会永远保存到数据库中。即使系统发生崩溃,事务执行的结果也不能丢失。

系统发生崩溃可以用重做日志(Redo Log)进行恢复,从而实现持久性。与回滚日志记录数据的逻辑修改不同,重做日志记录的是数据页的物理修改。

事务的目的是保障在任何情况下,不管是正常运行还是发生了系统故障,无论是单用户,串行执行还是多用户并发执行都要保证事务的执行。

关于锁和并发的问题放在下一章讲 [锁与并发](./数据库概论 (八))


日志系统

日志文件是用来记录事务对数据库的更新操作的文件,日志往往以记录为最小单位,或者以数据库定义的数据块为最小单位。

以记录为单位的日志文件的内容

  • 各个事务的开始标记(BEGIN TRANSACTION)
  • 各个事务的结束标记(COMMIT或ROLLBACK)
  • 各个事务的所有更新操作
  • 事务标识(标明是哪个事务)
  • 操作类型(插入、删除或修改)
  • 操作对象(记录内部标识)
  • 更新前数据的旧值(对插入操作而言,此项为空值)
  • 更新后数据的新值(对删除操作而言, 此项为空值)

重点是为了记录:哪个事务改变了哪个数据块。

登记日志文件的基本原则

  1. 登记的次序严格按照事务执行的时间次序登记
  2. 必须先写日志文件,再写数据库

并不是所有的操作都要写日志文件,只有在要把数据写到数据库中的时候才需要先写日志文件,再写数据库

因为可以通过日志文件恢复UNDO失败的数据库操作,如果先写数据库那么如果出现了错误就没有机会恢复刚刚的修改了。

恢复策略

事务运行过程中发生了故障

由恢复子系统利用日志文件撤销刚刚发生的对数据库的修改。此处的恢复操作是对用户透明的,用户不需要干预此处的修复。

  1. 从日志文件的末尾开始反向扫描日志文件,找到故障事务的数据库修改操作
  2. 执行修改操作的逆操作
  3. 继续反向扫描,遇到修改操作则执行2,直到抵达故障事务的开始语句。

系统故障导致的数据库状态不一致

造成不一致的原因

  • 未完成的事务的数据已经写入到数据库中
  • 已经提交的事务对数据库的修改还在缓冲区中,还没有执行修改

恢复的方法

  • Undo 针对未完成的,已经修改的操作
    • 反向扫描日志文件,对修改数据库的操作执行逆操作
    • 将更新前的值写入到数据库,覆盖数据
  • Redo 针对缓冲区中的操作
    • 正向扫描日志文件,找到每一个要执行数据库修改的操作
    • 将数据重新写入数据库

介质故障

首先要转入最新的,正常的数据库备份副本,使之恢复到最近的正常状态。

  • 对于静态存储的数据库副本,装入之后就已经处于一致性状态。
  • 对于动态存储的数据库副本,还要装入转储时刻的日志文件副本,使用Undo和Redo机制恢复到一致性状态。

然后对于备份之后的数据,我们要通过存储的日志文件来恢复,重做所有已经完成的事务。

  • 扫描日志文件,找出故障发生时已经提交的事务的标志,然后将其记入Redo队列,等待Redo
  • 然后正向扫描日志文件,对重做队列中的所有事务进行重做,然后写入数据库

数据库概论 (七)恢复技术

上一篇:docker+mysql集群+读写分离+mycat管理+垂直分库+负载均衡


下一篇:mysql字符集 utf8 和utf8mb4 的区别