可能的失败及其解决方法
失败类型
我们坑你遇到的失败或错误分为两大类:物理和逻辑。物理错误一般是硬件错误或使用数据库的应用程序中的软件错误,而逻辑错误一般在终端用户级别(数据库用户和管理员)。
按从轻到重、易恢复到难恢复排列:
- 语句失败:用户的SELECT或DML语句因权限、语法或资源限制而失败。
- 用户错误:用户误删了一个表或表中的行。
- 用户进程失败:与数据库的连接因为客户端断开或未预料的停机而失败。
- 网络失败:客户机和服务器(数据库)之间的网络连接因为网络硬件或协议错误而失败。
- 实例失败:数据库实例因为bug、操作系统错误、内存崩溃甚或服务器的功率损失而崩溃。
- 媒介失败:磁盘驱动物理错误或控制器硬件失败。
Oracle备份和恢复方法
- 恢复管理器(Recovery Manager,RMAN)是用于在表级别(12c新增)、数据文件、表空间和数据库级别上备份、还原和恢复数据库对象的主要工具。除了备份和恢复之外,RMAN还有许多用途,包括把数据库克隆或复制到另一个位置。RMAN的一个主要组件是备份和恢复对象的一个特定位置,称为快速恢复区(Fast Recovery Area,FRA)。这个区在理想情况下是ASM中的一个磁盘组,但也可以位于操作系统的文件系统上。无论位置在哪里,它都是所有备份和恢复对象的集中存储位置。FRA根据大小和恢复目标来管理,这是指根据恢复窗口或需要保留的备份数。使用FRA是可选的,但这是最佳实践方式。
- Oracle安全备份(Oracle Secure Backup,OSB)与RMAN一起提取RMAN备份,把它们复制到磁带设备或运存储中,以防止数据中心的灾难性故障而导致的数据丢失。OSB还提供了OS级别上的RMAN扩展,来备份Linux服务器和任何附加的存储,例如网络附加存储(NAS)设备。
- Oracle Data Guard是Oracle的一个可用性(HA)很高的解决方案,用于确保接近实时(因为主数据库失败)的可用性,或防止数据库崩溃。从主数据库的副本中实例化一个独立数据库(可以创建好几个独立数据库),从数据库中接收重做数据,来更新其数据文件。因此,独立数据库就与主数据库保持同步。独立数据库还可以临时用作数据库的只读副本,以用于生成报表,因此释放主数据库上的资源,在联机事务处理(OLTP)环境中有更短的响应时间。另一种独立数据库称为逻辑独立数据库。它不是持续不断地把重做数据应用于主数据库的物理副本,而是把重做操作转换为等价的DML SQL。因此,独立数据库在逻辑上等价于独立数据库,但几乎肯定没有与主数据库相同的物理结构。逻辑独立数据库并不是容错环境的一部分,而是一个优化为数据仓储的独立数据库,其中包含了与主数据库相同的数据。
实例恢复和数据库不可能崩溃
实例失败的原因有电力故障、重启服务器、发出SHUTDOWN ABORT命令,或导致实例后台进程终止、破坏System Global Area(SGA)的任何事情——所有这些都没有尝试把缓存中变更的缓存数据刷新到数据文件中,或者混滚任何正在进行的事务。
大体上,实例恢复只不过是使用联机日志文件的内容,将数据库缓冲区缓存重新构建至崩溃之前的状态。这个重构过程将重演在崩溃时未被写至磁盘的数据块的相关重做日志中提取出的所有变更。完成上述操作后,就能够打开数据库。此时,数据库仍然受到损坏,但是由于用户看到的实例已被修复,因此允许用户进行连接。实例恢复的这个阶段称为前滚,该阶段将恢复所有变更(也就是针对已提交和未提交事务的数据块变更与撤销块变更)。每条重做记录都具有重新构造一个变更所需的最少信息:数据块的地址以及新值。在前滚期间,会读取每条重做记录,相应的数据块从数据文件载入数据块缓冲区缓存,并且应用相应的变更,随后,数据块会被写回磁盘。
向前回滚结束后,崩溃看上去似乎从未发生过。不过此时数据库中还存在未提交的事务,这些事务必须被回滚,Oracle将在实例恢复的回滚阶段自动完成未提交事务的回滚操作。然而,上述操作则发生在数据库已被打开且使用之后。如果用户在连接时遇到某些需要回滚但是尚未回滚的数据,那么不存在任何问题。由于前滚阶段会填充保护未提交事务的撤销段,因此服务器能够以正常的方式回滚变更,从而实现度一致性。
实例恢复时自动的、不可避免的,那么如何才能调用实例恢复呢?答案是使用STARTUP命令。在实例启动时,加载控制文件之后,打开数据库之前,SMON进程会查看所有数据文件和连接重做日志文件的文件头。此时,如果已经出现了实例失败,由于文件头没有全部同步,因此SMON进程会发现实例失败,从而进入实例恢复例程,而数据库只能在前滚阶段结束之后才能被真正地打开。
如果执行了STARTUP命令,那么绝对不会丢失任何数据。在发生任何崩溃之后,都应当执行STARTUP命令并查看崩溃的程度。这个命令可以解决所有问题。
重做日志流中始终存在足够的信息,因此不仅能够重新构造发生崩溃前进行的所有操作,而且能够重新构造回滚崩溃时正在进行的事务所需的撤销信息。分析下面的场景:
用户John启动了一个事务。John使用某些新值更新某个表的一行,其服务器进程则将旧值复制至一个撤销段。但是完成这些更新之前,服务器进程会将变更写入日志缓冲区。用户Joo也启动了一个事务。两个用户都未提交事务,也没有在磁盘上写下任何数据。如果此时实例崩溃,那么不存在(甚至重做日志中也不存在)与任一个事务相关的记录。因此,两个事务都不会被恢复,但这并不是一个问题。因为都未被提交,所以不应当恢复这两个事务(未提交的工作绝不会被保存)。
随后,用户John提交了自己的事务。这个提交操作会触发LGWR进程将日志缓冲区中的内容刷新到联机重做日志文件,也就是说,此时重做日志文件内存在joh和Joo的事务对表和撤销段的更改以及针对John的事务的提交记录。只有在LGWR进程结束后,“commit complete(提交完成)”消息才会被返回给John的用户进程。但是,数据文件中仍然不会写入任何数据。如果此时实例失败,那么前滚阶段会重新构造这两个事务,不过处理完所有重做后仍然不会得到针对Joo的更新操作的提交记录,这将通知SMON进程回滚Joo所做的变更,同时保留John所做的变更。
然而,如果DBWn进程在实例崩溃前将某些数据块写入磁盘,那么又将出现怎样的情况呢?John(或者另一个用户)可能频繁地重新查询与其相关的数据,而Joo对数据进行了未提交的更改,并且不再查看这些数据。因此,DBWn进程将确定在磁盘上优先写入Joo所做的变更,然后再写入John所做的变更。DBWn进程总是会在磁盘上先写入不活跃的数据块,然后再写入活跃的数据块。因此,此时数据文件中存储了JOO的未提交事务,但是丢失了John的已提交事务。这是最糟糕的损坏类型。不过经过仔细考虑可以发现:即使此时实例崩溃,前滚仍然能够解决这个问题。重做流中始终存在重新构建已提交变更所需的足够信息,其原因显而易见,因为提交操作在DBWn进程完成写入之前不会结束。不过,因为LGWR进程将所有数据块的所有变更都写至日志文件,因此日志文件中也将存在重新构建撤销段所需的足够信息,从而能够回滚Joo未提交的事务。
综上所述,因为LGWR进程总是先于DBWn进程进行写操作,并且在提交的同时进行实时的写操作,所以在重做流中始终存在足够的信息,从而能够重新构建任何已提交的未被写入数据文件的变更,回滚任何已被写入数据文件的未提交变更。只要没有受到物理损坏,重做与回滚这种实例恢复机制就能够使Oracle数据库绝对不被破坏。
执行SHUTDOWN ABORT命令会损坏数据库吗?答案是绝对不会!这个命令不可能损坏数据库。只要联机日志文件可用,实例恢复机制就总是可以恢复任何损坏的数据。
检查点和重做日志
检查点机制
检查点位置(崩溃后,重做流中的实例恢复起点)由DBWn自动前移。这个过程称为“增量检查点(incremental checkpointing)”。除此之外,还有“完整检查点(full checkpointing)”和“局部检查点(partial checkpointing)”。
增量检查点是正常数据库活动的一部分。DBWn进程决定缓存中是否有足够的、已更新的块,是否应把其中的几个写入磁盘。选择写入哪些变更的缓冲区的算法,是基于更改时多久以前进行的,以及如何激活缓冲区。
在一般情况下,只有缓冲区已更改,且是空闲的,才能写入该缓冲区。永远不要忘记,提交变更和把块写入磁盘之前没有相关性,DBWn只写入所需的最少块数。
如果将素有脏缓冲区都写入磁盘,就会出现完整检查点。在常规运行中,缓存中可能存在一百万个脏缓冲区,但对于增量检查点,DBWn只写入其中的数百条。而对于完整检查点,它将写入这些内容。为此,必须完成大量的工作:在执行检查点时,需要非常高的CPU使用率和磁盘使用率,用户会话的性能会随之降低。完整检查点会对业务产生负面影响。鉴于此,只有在两种情况下才执行完整检查点,第一种情况是有序关闭,第二种情况是DBA要求这么做。
当使用NORMAL、IMMEDIATE或TRANSACTIONAL选项关闭数据库时,都会执行检查点:在关闭和卸载数据库之前,DBWn会将所有的脏缓冲区刷新到磁盘中。这意味着,再次打开数据库时,不需要执行任何���复操作。在执行某些操作(如启用归档日志模式)前,始终希望(也有必要)执行干净关闭。使用以下命令,可以在任何时间发出完整检查点信号:
alter system check point;
对于某些操作而言,局部检查点是必须的,并会自动执行。局部检查点影响的缓冲区因操作而异:
操作 | 从缓存中刷新哪些缓存区 |
---|---|
使表空间脱机 | 表空间中的所有块 |
使数据文件脱机 | 数据文件中的所有块 |
删除区间 | 区间中的所有块 |
截断表 | 表中的所有块 |
将表空间置于备份模式 | 表空间中的所有块 |
用RMAN备份数据文件 | 数据文件中的所有块 |
只有在执行有序关闭或发出请求时,以及应DBA请求时才会执行完整检查点。而局部检查点将根据需要自动执行。
保护联机重做日志文件
Oracle数据库运行时至少需要两个联机重做日志文件组, 从而能够在两个组之间进行切换。考虑到性能因素,可能需要添加更多的联机重做日志文件组,但两组是必需的。每个组都由一个或多个成员组成,这些成员是物理文件。运行Oracle数据库只要求每个组有一个成员,但是为了安全起见,每个组至少都应当具有两个成员。
DBA不允许丢失当前联机日志文件组的所有备份。如果出现这种情况,就会丢失数据。在丢失当前联机日志文件组的素有成员时,不丢失数据的唯一方法是,配置一个无数据 损失的Data Guard环境,不过比较复杂。为什么说不丢失但钱联机日志文件组的所有成员直观重要呢?答案与实例恢复有关。实例崩溃后,SMON进程会使用当前联机日志文件组的内容进行前滚恢复,从而修复数据库中的任何损坏。如果当前联机日志文件组不可同,可能是由于未被多路复用,一个成员因介质受损而被破坏,那么SMON进程无法进行前滚恢复。如果SMON进程无法通过前滚修正数据库的损坏,那么不能打开数据库。
如果重做日志文件组的一个成员被损坏或丢失,那么数据库在存在备份成员的情况下,仍然会保持打开状态。这与控制文件不同,控制文件任何副本的损坏都会使数据库立即崩溃。同样,只要存在至少两个重做日志文件组,每个组都至少有一个有效的成员,那么在数据库打开时,也可以添加或移动重做日志文件组以及组中的成员。
在打开数据库时,无须停机,联机重做日志就可以重新配置,而数据库在非加载模式下或完全关闭时,才能执行控制文件中的操作。
VLOG视图给每个组显示一行,VLOGFILE视图给每个日志文件成员显示一行。
SYS@ prod>select group#,sequence#,members,status from v$log;
GROUP# SEQUENCE# MEMBERS STATUS ---------- ---------- ---------- ---------------- 1 10 1 CURRENT 2 8 1 INACTIVE 3 9 1 INACTIVE
SYS@ prod>select group#,status,member from v$logfile;
GROUP# STATUS MEMBER ---------- ------- ------------------------------ 3 /u01/oradata/prod/redo03.log 2 /u01/oradata/prod/redo02.log 1 /u01/oradata/prod/redo01.log
SYS@ prod>alter system switch logfile;
System altered.
SYS@ prod>select group#,sequence#,members,status from v$log;
GROUP# SEQUENCE# MEMBERS STATUS ---------- ---------- ---------- ---------------- 1 10 1 ACTIVE 2 11 1 CURRENT 3 9 1 INACTIVE
SYS@ prod>
第一个查询说明该数据库有三个日志文件组。此时LGWR进程正在写的当前组是组1(status - current),其他两个组是不活动的。SEQUENCE#列说明从创建数据库以来(或者使用ALTER DATABASE OPEN RESETLOG重置日志顺序以来)总共发生过10次日志切换。MEMBER列说明每个组都由一个成员组成。
第二个查询显示了不同的联机重做日志文件。其中,每个文件都是由GROUP#标识的一个组的一部分,并且具有唯一的名称。STATUS列应当时钟为空。如果该成员未使用(原因通常是数据库刚打开,尚未发生日志切换),那么其状态为STALE,并且一直会持续到发生第一次日志切换时。如果日志文件成员的状态为INVALID,则说明存在问题。
命令lter system switch logfile强制执行日志切换。
最后一个查询说明在日志切换后,组2成为LGWR进程进行写操作的当前组,序列号切换为11。先前的当前组(组1)的状态变为ACTIVE,这以为着如果此时出现实例失败,SMON进程仍然需要使用组2来进行实例恢复。稍后,由于检查点位置前移,因此这个组的状态不久将变为INACTIVE。
为了防止数据库在联机重做日志文件组受到破坏时丢失数据,请准备多路复用副本。可以给每个日志文件组使用下面的命令,将多路复用副本添加到联机日志中:
alter database add logfile member 'D:apporaleoradataredo01a.log' to group 1;
归档日志模式和归档器进程
将数据库改为归档日志模式能够确保:如果联机重做日志文件组没有首先被复制为归档日志文件,那么不能被重写。这样将存在一系列归档日志文件,这些文件描述了应用于数据库的所有变化的完整历史。如果一个数据文件在某个时刻被破坏,那么可以还原该数据文件的一个备份,并应用归档日志重做流中的变更,从而使这个数据文件是最新的。
在默认情况下,数据库时在非归档日志模式中创建的,这意味着日志切换在没有先进行复制的情况下会重写联机重做日志文件。此时数据库仍然不会受损,但是如果数据文件因为介质失败被损坏,那么会丢失数据。在数据库被转换至归档日志模式时,如果从最近一次数据库备份开始生成的所有归档日志文件都可用,那么不会丢失数据。
一旦数据库被转换至归档日志模式,就会自动启动一个新的后台进程:归档器进程ARCn。在默认情况下, Oracle会启动4个这样的进程,不过在实际应用中最多可以启动30个。
Oracle实例使用ARCn进程维护归档日志的创建过程,但是DBA必须通过使用操作系统命令或RMAN来控制到磁带的迁移过程。
数据库只有在干净关闭后处于加载模式时,才能转换至归档日志模式,并且必须由建立了SYSDBA连接的用户完成。此外,还必须设置若干初始化参数,来控制所生成的归档日志名称和位置。
配置快速恢复区
快速恢复区是一个磁盘目标,用作与恢复相关的文件的默认位置。可以使用两个实例参数对快速恢复区进行控制:
- db_recovery_file_dest :指定位置。这可以使文件系统目录或ASM磁盘组。多个数据库可以共享一个公共目标;在目标中,每个数据库都有各自自动创建的目录结构。
- db_recovery_file_dest_size :限制数据库将要在目标中占用的最大空间量,但不能说明目标中实际可用的空间大小。
快速恢复区的配置和使用在两个视图中显示:
- v$recovery_file_dest
- v$recovery_area_usage
写入快速恢复区(除非另外指定)的文件包括:
- 恢复管理器备份
- 归档重做日志文件
- 数据库闪回日志
RMAN可以管理快速恢复区中的空间:它可以根据已配置的关于保留文件副本和备份的策略,删除不再需要的文件。在理想状况下,快速恢复区将足够大,可以存储完整的数据库副本、在必要时恢复副本所需的任何归档日志和增量备份,以及联机重做日志文件和控制文件的多路复用副本。
数据库备份例程还应包括将快速恢复区备份到磁带,从而实现一级、二级和三级存储的策略。
- 一级存储是磁盘中使用的数据库。
- 二级存储是数据库的副本以及快速恢复需要的文件。
- 三级存储是磁带库中的长期备份。
RMAN可以管理整个周期:将数据库从一级存储备份到二级存储,并将备份从二级存储迁移到三级存储。可以将这样的系统实现为在故障之后能接近瞬时恢复,同时能在必要时及时恢复数据库。
快速恢复区可以随时配置,不会影响其中的任何文件。变更只应用于之后创建的文件。
配置ARCHIVELOG模式
切换为归档日志模式的过程:
- 干净地关闭数据库。
- 以装载模式启动。
- 执行命令ALTER DATABASE ARCHIVELOG;
- 打开数据库
- 执行完整备份。