24.1 概述
数据库系统在运行过程中可能会发生一些故障。造成故障的原因多种多样,包括磁盘崩溃、电源故障、软件错误,甚至人为破坏。故障情况一旦发生,就可能导致丢失数据,数据库系统将无法正常运行。因此,故障恢复是数据库系统必不可少的组成部分,即数据库系统必须保证即使发生故障,也可以保障数据的完整性和一致性。
目前支持故障恢复的主要技术是日志。日志以一种安全的方式记录了数据库系统变更的历史信息,一旦系统出现故障,数据库系统可以根据日志将系统恢复至故障发生前的某个时刻。数据库系统的日志分为两种类型:一是 REDO 日志(即重做日志),每当在数据库中指定 DDL 及 DML 操作后,DM 都会按照特定的格式,生成一条 REDO 日志记录登记该操作,并记录操作后的数据;另一种是 UNDO 日志,UNDO 日志中记录进行 DML 操作之前的原始数据信息。
另外,当服务器处于归档模式时,如果数据库发生故障,通过备份文件和归档日志可以恢复到指定时间点。
24.2 REDO 日志
在恢复操作中最重要的结构是联机 REDO 日志。REDO 日志存放在联机日志文件中,这些文件存储数据库所做的所有物理更改信息。达梦数据库每一个实例都默认会生成两个相关联的联机日志文件,通过 REDO 日志可以保证数据库的完整性和一致性。
DM SERVER 的 REDO 日志用于存储被 DML 或 DDL 操作后数据的新值,包括事务对数据文件和回滚段的修改。REDO 日志每次被修改后,都会自动生成一个新的日志序列值 LSN(Log Sequence Number)。LSN 取值范围 0~正无穷大,新建的库 LSN 为 0,以后日志每被写入一次,LSN 值增加 1。
REDO 日志里包含有一种特殊的记录,叫 PWR(Page Written Record)日志。PWR 包括(ts_id, fil_id, page_no, page_lsn)信息。每个数据页刷盘时,都会生成一条对应的 PWR 日志。PWR 日志的 LSN 与上一个日志的 LSN 相同。在以下情况下可以利用 PWR 日志:
- DSC 故障恢复时:利用 PWR 日志减少加载磁盘数据页的次数;
- 故障恢复时:利用 PWR 日志提升 redo 速度;
- 增量备份时:利用 PWR 日志提升备份速度。
日志文件由日志表空间(RLOG)管理。DM 支持增加日志文件和扩展日志文件大小。
例 1 增加大小为 80M 的日志文件 dameng_003.log
ALTER DATABASE ADD LOGFILE 'dameng_003.log' size 80;
例 2 将日志文件 dameng_003.log 大小更改为 100M
ALTER DATABASE RESIZE LOGFILE 'dameng_003.log' to 100;
在 MOUNT 状态下,支持对日志文件的重命名操作。
例 3 将日志文件 dameng_003.log 重命名为 dameng_004.log
ALTER DATABASE RENAME LOGFILE 'dameng_003.log' to 'dameng_004.log';
24.3 重做日志归档
DM 服务器可以运行在两种模式下,即归档模式和非归档模式,这两种模式可以由用户进行设置,系统在归档模式下运行时,会产生归档日志文件,此时系统管理员应该事先预留出足够的磁盘空间以便存储归档日志文件。通过调整 dm.ini 和 dmarch.ini 文件参数可以配置归档,参见[第 2 章 DM 物理存储结构](#第 2 章 DM 物理存储结构)。DM 支持以下六种归档类型:
24.3.1 本地归档
本地归档就是将 REDO 日志写入到本地归档文件。本地归档在 REDO 日志写入联机日志文件后触发,由归档线程完成本地归档动作,最多可以设置 8 个本地归档。
与联机 Redo 日志文件可以被覆盖重用不同,本地归档日志文件不能被覆盖,写入其中的 Redo 日志信息会一直保留,直到用户主动删除;如果配置了归档日志空间上限,系统会自动删除最早生成的归档 Redo 日志文件,腾出空间。
为了最大限度地保护数据,当磁盘空间不足导致归档写入失败,系统将自动挂起等待,直到用户主动释放出足够的空间后继续运行。在设置多路本地归档的情况下,如果第一路本地归档的磁盘空间不足,则系统会被强制挂起,直到磁盘空间释放后继续运行。其它本地归档可以通过在 dmarch.ini 中设置 ARCH_HANG_FLAG 参数表示本地归档写入失败系统是否挂起,缺省值为 1,表示本地归档写入失败系统挂起。此外,系统会定期尝试恢复 INVALID 的本地归档状态为 VALID。恢复 VALID 状态之后,如果正好剩余磁盘空间充足,那么可以继续归档。但是其它路(第一路归档之外的)本地归档中缺失的归档就需要人工手动进行修复了。当磁盘损坏导致归档日志写入失败时,系统会强制 HALT。
24.3.2 实时归档
实时归档的执行流程为:主库在写入 REDO 日志到联机日志文件之前,通过 MAL 系统发送 REDO 日志到备库,备库收到 REDO 日志后,不需要等待 REDO 日志重演完成,马上响应主库,返回确认消息。主库收到确认消息后,执行后续操作,将 REDO 日志写入联机日志文件;若发送 REDO 日志失败,或从备库返回的数据库模式不是 STANDBY,将数据库切换为 SUSPEND 状态,阻塞所有 REDO 日志的写入操作。一个主库可以配置 1~8 个实时备库。
根据备库重演 REDO 日志和响应主库时机的不同,实时归档可以分为两种模式:事务一致模式和高性能模式。实时归档默认采用高性能模式。
对事务一致模式与高性能模式的详细说明,请查看《DM8 数据守护与读写分离集群 V4.0》。
24.3.3 即时归档
即时归档在主库将 REDO 日志写入联机日志文件后,再通过 MAL 系统将 REDO 日志发送到备库,在默认模式下备库会在收到 REDO 日志并重演完成后,再响应主库。即时归档与实时归档的主要区别是发送 REDO 日志的时机不同,即时归档在主库 REDO 日志写入联机日志文件之后发送,实时归档在主库 REDO 日志写入联机日志文件之前发送。即时归档是读写分离集群的实现基础。一个主库可以配置 1~8 个即时备库。
根据备库重演 REDO 日志和响应主库时机的不同,即时归档也可以分为两种模式:事务一致模式和高性能模式。即时归档默认采用事务一致模式。
对事务一致模式与高性能模式的详细说明,请查看《DM8 数据守护与读写分离集群 V4.0》。
24.3.4 异步归档
异步归档由在主、备库上配置的定时器触发,在设定的时间点或者每隔设定时间,启动归档 REDO 日志发送。设置异步归档,必须确保至少有一个本地归档。根据异步备库的 KEEP LSN 信息,扫描本地归档目录获取 REDO 日志,并通过 MAL 系统将 REDO 日志发送到异步备库,备库收到 REDO 日志后,将其加入日志重演任务系统,并马上响应主库,不需要等待 REDO 日志重演结束后再响应主库。最多可以设置 8 个异步归档。
24.3.5 同步归档
主库在归档日志刷盘后,通过 MAL 系统将 REDO 日志发送到备库,备库收到 REDO 日志后,将其加入日志重演任务系统,并马上响应主库,不需要等待 REDO 日志重演结束后再响应主库。同步归档与异步归档的区别是,同步归档不依赖定时器,主库归档日志刷盘后立即将归档日志发送到备库。一个主库可以配置 1~8 个同步备库。
24.3.6 远程归档
远程归档专门用于 DMDSC 环境中,是将当前节点的远程归档目录配置为另一节点的本地归档目录,以此来共享它的本地归档日志文件。远程归档采用双向配置的方式,即两个节点将自己的远程归档相互配置在对方机器上。DMDSC 集群配置远程归档后,集群中任意实例都可以像访问本地归档一样,访问所有实例产生的归档日志。
24.4 检查点
创建数据库时,联机日志文件通常被扩展至一定长度,其内容则被初始化为空,当系统运行时,该文件逐渐被产生的日志所填充。为了达到循环利用日志系统空间的目的,必须在所有日志文件空间将被占满时,系统能够自动清空一部分日志,以便重用日志文件的空间,为了保证被清空的日志所“保护”的数据在磁盘上是安全的,需要引入一个关键的数据库概念——检查点。当系统产生检查点时,将系统缓冲区中被修改过的数据页写入磁盘,以保证当前日志所“保护”的数据页都已安全写入磁盘,这样日志文件即可被安全重用。
当服务器启动和关闭时,系统都会产生检查点。服务器运行过程中,系统会自动判断是否需要执行检查点;当空闲日志空间不足时,系统自动产生一个检查点;系统调度线程也会定时产生检查点;还可以通过调用系统函数 CHECKPOINT 主动生成检查点。
系统调度线程根据 dm.ini 的参数配置,产生检查点,下面给出具体的例子和说明。
CKPT_INTERVAL = 1800 ##每间隔1800秒,产生检查点间隔
CKPT_FLUSH_RATE = 5 ##检查点的刷盘比例为5%,将系统中所有脏页的5%写入磁盘
CKPT_FLUSH_PAGES = 1000 ##一个检查点最少写入1000个脏页
检查点系统函数 CHECKPOINT(FLUSH_RATE),其参数 FLUSH_RATE 为 INTEGER 类型或 DOUBLE 类型,指示刷盘比例,替代 dm.ini 中的 CKPT_FLUSH_RATE,同时 CKPT_FLUSH_PAGES 参数同时生效。例如,执行 SELECT CHECKPOINT(10);会将系统中 10% 脏页写入磁盘。
24.5 回滚段与回滚记录
DM SERVER 采用回滚段机制来处理 UNDO 日志。回滚段由一定数量的回滚页组成,回滚页存放的是一批回滚记录。回滚记录存放被修改数据的旧值,并有专属的格式,与物理记录格式不同。回滚段的管理同一般数据文件一样,其回滚数据页的分配、淘汰和释放也交由数据缓冲区完成。回滚文件属于回滚表空间。回滚段的数据并不会永久保留, 事务结束后,由系统的 PURGE 模块释放回滚页。
REDO 日志记录了所有对数据库数据进行修改的数据,当然也包括回滚段的修改数据。因此,REDO 日志同样也会保护回滚数据。当使用重做日志恢复数据库时,系统将重做回滚段中修改了的数据,并将这些修改写回到回滚段中,从而形成回滚记录。回滚记录与重做记录类似,只不过回滚记录记录被修改数据的旧值,以达到数据回滚到原来状态的目的。
另外,回滚表空间不允许修改和删除操作。
24.6 系统故障恢复
系统故障也就是我们通常所说的系统崩溃。系统崩溃的原因比较复杂,有硬件故障,或者是数据库软件或操作系统的漏洞等。它导致整个系统停止运行,内存中的数据全部丢失,但磁盘上存储的数据仍然有效。
当系统故障发生时,系统管理员可以通过查看系统日志文件以了解系统故障发生的原因或故障发生之前系统的运行状况。多数情况下,系统在故障发生之前会自动记录产生故障的原因,但也不全是这样,如系统掉电时,发生故障的原因可能来不及记录。总之,在处理系统故障之前,系统管理员需要完全了解系统故障发生的原因,并采取相应的措施,如更换硬件,升级操作系统或数据库软件等,必要时还可以联系达梦公司的技术支持工程师,以获得必要的支持。
系统故障恢复的最后一步则是重新启动 DM 服务器。此时,系统将从最近一个检查点处开始扫描联机日志,并重做日志记录的内容,这样系统即恢复到了故障发生前的某个很近的时刻,然后将系统中仍然活动的事务再依次利用回滚段进行回滚。由此可以看出,系统故障恢复可以保证事务的原子性和持久性,即系统故障发生时,仍然活动的事务可以被安全回滚,而已经提交的事务则保证其所修改数据的持久性。
24.7 介质故障恢复
介质故障指的是由于各种原因导致数据库系统存储在磁盘上的数据被损坏,如磁盘损坏等。介质故障是数据库系统最为严重的故障,此时系统已经无法重新启动,磁盘上的数据也无法复原。
出现介质故障后,系统管理员首先需要分析介质故障发生的原因,并采取措施,如磁盘损坏则更换磁盘等。由于系统的数据已经全部或部分丢失,此时只能依赖以前建立的备份和系统产生的归档日志文件进行恢复。由于涉及到备份,具体的介质恢复策略将在《DM8 备份与还原.docx》中详细介绍。
需要说明的是,为了避免系统在出现故障时丢失数据,应关闭磁盘缓存(若存在的话),具体事项请咨询操作系统管理员。